Несколько (случайно выбранных) выходов при разных запусках одной и той же программы.Случайные символы добавляются при fscanf'ing - PullRequest
0 голосов
/ 28 ноября 2018

Простая программа: читает имя и фамилию (Джон Смит) из файла .txt через fscanf, добавляет пробелы, печатает имя в консоли (так же, как оно написано в .txt).

Если скомпилировано и запущено на Win10 через

Microsoft (R) C / C ++ Оптимизирующая версия компилятора 19.14.26433 для x86

, следующий код не выдаст тот же вывод дляодин и тот же ввод для разных .exe запусков (без перекомпиляции).Кажется, что для каждого входа имеется несколько выходов, между которыми программа выбирает случайным образом.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() 
{
    char input_file_name[255];
    FILE * input_file;
    char name[255];
    input_file = fopen ("a.txt","r");
    do
    {       
        if (strlen(name) != 0 )
            name[strlen(name)] = ' ';

        fscanf (input_file, "%s", name + strlen(name) * sizeof(char));
    }while(!feof(input_file));
    fclose (input_file);
    printf("Name:%s\n", name);
    system("pause");
    return 0;
}

Я перечислю пару входов и выходов для них.Поскольку не все символы пригодны для печати, я буду печатать их как \ ascii_code, например, \ 97 = a.Наиболее распространенные аномалии: \ 31 (разделитель единиц) добавляются в самом начале строки и \ 12 (подача формы NP, новая страница) или \ 17 (элемент управления устройства 1) прямо перед фамилией (после первого пробела).

  1. Для "Джона Смита":

    • "Джона Смита" (правильный вывод)
    • "\ 31 Джона Смита"
  2. Для "Atoroco Coco"

    • "Atoroco \ 12Coco"
    • "\ 31 Atoroco \ 16Coco"
  3. Для "Микки Мауса"

    • "Микки Маус" (собственно)
    • "\ 31 Микки \ 81Мышка" (есть \ 32 (пробел)) в строке прямо перед \ 81, но консоль не показывает пробел?!)

Если скомпилирован другой компьютер (MacOS, компилятор неизвестен), кажется,для правильной работы каждый раз, то есть он просто печатает содержимое .txt.

Почему создается несколько выходных данных, казалось бы, наугад?Почему эти символы (\ 31, \ 12 и т. Д.), В частности, добавлены, а другие нет?

1 Ответ

0 голосов
/ 28 ноября 2018

Ваш код вызывает Неопределенное поведение (UB), поскольку он использует name неинициализирован.Подробнее в Что такое неопределенное поведение в C?

Мы инициализируем его и убедимся, что здесь установлен нулевой терминатор.Стандартные строковые функции, такие как strlen(), зависят от нулевого терминатора для обозначения конца строки.

Затем вам необходимо убедиться, что вы что-то прочитали, прежде чем вызывать feof().Кроме того, неплохо проверить, что возвращает fscanf(), что обозначает количество прочитанных элементов.

Собрав все вместе, мы получим:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() 
{
    char input_file_name[255];
    FILE * input_file;
    char name[255] = "\0"; // initialize it so that is has a  null terminator
    input_file = fopen ("a.txt","r");
    do
    {       
        if (strlen(name) != 0 )
            name[strlen(name)] = ' ';
    } while (fscanf (input_file, "%s ",  name + strlen(name) * sizeof(char)) == 1 && !feof(input_file));
    fclose (input_file);
    printf("Name:%s\n", name);
    return 0;
}

Вывод (для «Георгиос Самарский»):

Георгиос Самарский

...