Почему fgets() и/или fputs() удаляют пробелы из моей строки?

Я пытаюсь получить строку пользовательского ввода и записать ее в файл. Однако независимо от того, что я делаю, в выводе всегда удаляются пробелы из строки.

Я думал, что вся цель использования gets()/puts() заключалась в том, что он будет читать/выводить все символы в строке, пока не встретит символ новой строки.

Может кто-нибудь, пожалуйста, скажите мне, что я делаю неправильно??

int main (void){
    char userInput[100];
    char filename[50];
    FILE *cfPtr;

    printf("Enter name of file to open: ");
    scanf("%s", &filename);

    cfPtr = fopen(filename, "a+");

    printf("Enter text to add to file: \n");
    fgets(userInput, 100, stdin);

    while (strcmp( userInput, "0") != 0) {
        fputs( userInput, cfPtr);
        fgets(userInput, 100, stdin);
    } // end while

    fclose( cfPtr );

    system("pause");
} // end main

person tbutman    schedule 23.07.2013    source источник
comment
0 не является символом новой строки. Это 0. И вы сравниваете целую строку с 0, а не только с символом. Может быть, вы имели в виду fgetc?   -  person Jiminion    schedule 23.07.2013
comment
Извините, я должен был объяснить это немного. Я проверяю строку на «0», чтобы программа завершилась, если пользователь введет ноль. В противном случае в текстовый файл будет записано все, кроме 0.   -  person tbutman    schedule 23.07.2013
comment
Я все еще не думаю, что strcmp будет работать, если только пользователь не поставит один 0, чтобы закончить?   -  person Jiminion    schedule 23.07.2013
comment
Нужно ли очищать или сбрасывать пользовательский ввод?   -  person Jiminion    schedule 23.07.2013
comment
Правильно, пользователь должен ввести один 0 в конце.   -  person tbutman    schedule 23.07.2013
comment
Я попытался добавить fflush(stdin) перед оператором fgets, но, к сожалению, проблема все еще остается :(   -  person tbutman    schedule 23.07.2013
comment
@user2611922 user2611922 fflush(stdin); - это неопределенное поведение. Пожалуйста, не читайте этот Читать-ответ   -  person Grijesh Chauhan    schedule 24.07.2013


Ответы (3)


Может кто-нибудь, пожалуйста, скажите мне, что я делаю неправильно??

Первая ошибка, которую я могу заметить, это в scanf, для строки с %s вы используете &:

scanf("%s", &filename);
            ^
            |
            remove it, undefined behavior

это должно быть просто:

scanf("%s", filename);

ваш код не будет работать после этого. Я не могу найти никакой другой синтаксической ошибки, поэтому я считаю, что это основная ошибка в вашем коде.

person Grijesh Chauhan    schedule 23.07.2013
comment
Это очень хороший и правильный пункт с UB, OP даже не должен смотреть дальше, прежде чем исправлять эту ошибку. Однако я не вижу причин, по которым это не сработает :) - person ; 23.07.2013
comment
@H2CO3 Не понял :( :( I don't see any reason why it wouldn't work ? Мне нужно улучшить/изменить ответ? - person Grijesh Chauhan; 23.07.2013
comment
Нет, не знаешь. Я просто указываю, что, хотя бессмысленно пытаться рассуждать о UB, я все же ожидаю, что этот конкретный случай сработает :) - person ; 23.07.2013
comment
Я согласен с г-ном Кислотой, точка зрения верна, но я не думаю, что это проблема. Компиляторы легко справляются с такими вещами. - person Jiminion; 23.07.2013
comment
Кроме того, просто чтобы уточнить, хотя я оставил амперсанд в своем первом операторе scanf, технически это не нормально, поскольку имя массива указывает на местоположение первого элемента (не &array, array, &array[0] все равно расположению в памяти начала массива)? - person tbutman; 23.07.2013
comment
@user2611922 Нет, прочитайте: Что возвращает sizeof(&arr) ? - person Grijesh Chauhan; 23.07.2013
comment
@user2611922 user2611922 именно поэтому я не стал объяснять дальше. читать последний лайк и комментарии от H2CO3. - person Grijesh Chauhan; 23.07.2013
comment
Попался. Тем не менее, спасибо за ссылку, Грижеш. Будучи очень новичком в программировании, я думаю, что это будет очень информативно. - person tbutman; 23.07.2013
comment
Но это не отвечает на вопрос. - person Jiminion; 24.07.2013
comment
@Джим почему? не отвечает, предложите мне, если я пропал, или вы можете опубликовать свой собственный ответ... - person Grijesh Chauhan; 24.07.2013
comment
Я все еще не думаю, что амперсанд имеет значение в этом случае при использовании массива с функцией scanf, так как функция ожидает адрес памяти. В этом случае &array, array и &array[0] указывают на один и тот же адрес в памяти, поэтому это не должно иметь каких-либо негативных последствий для кода, не так ли? - person tbutman; 24.07.2013
comment
@user2611922 user2611922 хорошо, я отвечу вам, сначала попробуйте запустить свой код без &, затем дайте мне знать, что произошло и что вы хотите - person Grijesh Chauhan; 24.07.2013
comment
Это не отвечает на вопрос, почему его пробелы удалены. Эй, пользователь 2611922, можешь показать ввод и как он меняется при вводе в файл? - person Jiminion; 24.07.2013
comment
@Grjesh На моей машине код работает одинаково с амперсандом и без него. Однако ни один из способов не решает мою проблему с удалением пробелов, но, по крайней мере, я знаю, что мой код работает на других машинах. - person tbutman; 24.07.2013
comment
@user2611922 user2611922 Я еще раз взглянул на ваш код, я не обратил внимания, так как нашел его в разделе «Неопределенное поведение». - person Grijesh Chauhan; 24.07.2013
comment
@Jim It doesn't answer the question не работает, либо предложите улучшение, либо опубликуйте свой ответ. - person Grijesh Chauhan; 24.07.2013
comment
@ user2611922 вы вводите 0 для завершения цикла while? - person Grijesh Chauhan; 24.07.2013
comment
@Jim Если я введу текстовую строку, это строка, в консоль, результирующий текстовый файл будет иметь thisisaststring. - person tbutman; 24.07.2013
comment
@Grjesh, да, 0 для завершения. Пока похоже, что эта проблема специфична для моей машины :( - person tbutman; 24.07.2013
comment
@ user2611922 1. инициализированный массив, например. char userInput[100] = {0}; 2. открыть файл в режиме w не a+ прочитать о нем отличия. 3 при следующей попытке -- удалить ранее созданный идентификатор файла, который вы используете в режиме a. - person Grijesh Chauhan; 24.07.2013

1) fgets() и fputs() не удалят пробелы из вашей строки.

2) Одна потенциальная ошибка заключается в том, что fgets() БУДЕТ сохранить символы "Enter", которые вы, вероятно, не считаете частью своей строки.

3) Проблема в вашем коде, вероятно, связана с вашим "scanf()" - вы должны передать "имя файла" (которое является массивом) вместо "& имя_файла" (которое дублирует избыточность).

4) Еще лучше, вы можете подумать о замене "fgets()" на "scanf()".

ИМХО...

PS: Вот отличная ссылка на использование fgets() и друзей:

http://beej.us/guide/bgc/output/html/multipage/gets.html

person paulsm4    schedule 23.07.2013
comment
Спасибо всем за отзывы, но, похоже, что-то не так с моим компилятором, потому что я все еще испытываю ту же проблему с удалением пробелов. Если я ввожу строку add this string, она записывает строку addthisstring в файл. Так что я не уверен, что происходит. Может ли кто-нибудь попробовать запустить код на своей машине, чтобы увидеть, смогут ли они заставить его работать правильно? - person tbutman; 23.07.2013
comment
Работает на меня. Вроде. пришлось сравнить 0\n для учета новой строки. Пространства вроде сохраняются. система(пауза) не работала. Вы на какой ОС? - person Jiminion; 23.07.2013
comment
У меня Windows 7. Спасибо, что подтвердили, что это работает!! Я возился с этим кодом больше часа, пробуя каждую комбинацию fgets/gets/scanf и соответствующих функций печати/пути, пытаясь заставить его работать. По крайней мере, теперь я знаю, что это не код. Может это как-то связано с моим компилятором или проектом на Visual Studio?? Я буду продолжать возиться с этим. Спасибо еще раз! - person tbutman; 24.07.2013
comment
Visual C++ работает немного иначе, чем g++. Есть некоторые отличия. Я бы также добавил %s\n для захвата имени файла. Кажется, что без него в вывод добавляется дополнительная строка новой строки. - person Jiminion; 24.07.2013

Это работает под g++ и linux.

int main (void){  
  char userInput[100];  
  char filename[50];  
  FILE *cfPtr;

  printf("Enter name of file to open: ");  
  scanf("%s\n", filename);

  cfPtr = fopen(filename, "a+");

  printf("Enter text to add to file: \n");  
  fgets(userInput, 100, stdin);

  while (strcmp( userInput, "0\n") != 0) {  
      fputs( userInput, cfPtr);  
      fgets(userInput, 100, stdin);  
  } // end while

  fclose( cfPtr );

  //system("pause");  
} // end main
person Jiminion    schedule 23.07.2013