Как преобразовать значения, которые я получаю из файла (char), и сохранить значения в массив двойных значений?

Я читаю данные из файла, получая, сколько столбцов и строк у меня есть (файл данных), все до сих пор. Теперь я пытаюсь прочитать значения одно за другим и сохранить значения в двумерном массиве (двойном). Я получаю значения как char, используя getc, но когда я пытаюсь использовать atoi или atof для преобразования значений из char в double, я получаю странные значения.

double ther[j][number];
char c;
int tim=0,nther=0;


FILE *fp3 = fopen("data.txt", "r");
c = getc(fp3) ;

while (c!= EOF)
{ 

    ther[tim][nther]=atoi(&c);
    printf("%lf", ther[tim][nther]);


    nther++;
    c = getc(fp3);

    if(nther==number)
    {
        tim++;
        nther=0;
    }
    tim=0;
}

fclose(fp3);

любое предложение?… (я продолжаю искать). Извините, у меня есть файл data.txt, и в этом файле есть строки и столбцы чисел:

1 2 3 4 5

6 7 8 9 10

Итак, мне нужно сохранить данные в 2D-массив: благодаря ответам у меня есть некоторые идеи, например: использовать строку, затем разделить все значения и сохранить каждое из них. 1-я строка - это строка-> массив [0] [0], массив [0] [1] и т. д. Затем перейдите к другой строке и сделайте то же самое.

До сих пор я получаю некоторые числовые значения, но ни одно из них не хранится в data.txt.


person mrmurmanks    schedule 28.03.2014    source источник
comment
Попробуйте выполнить отладку с помощью gdb. Вы узнаете, что именно происходит. Перейдите по этой ссылке.   -  person Jigar    schedule 28.03.2014
comment
Хорошо, давно с тех пор, как я использовал GDB :)   -  person mrmurmanks    schedule 28.03.2014


Ответы (3)


Во-первых, это должно быть int c;. Функция getc() должна иметь возможность возвращать другое значение для всех возможных char, а также другое значение EOF (которое означает конец файла или ошибку потока).

Если вы используете char c;, то вы должны в конечном итоге преобразовать EOF в значение допустимого символа, поэтому вы не сможете увидеть разницу между двумя случаями. Другими словами, ваш код может действовать так, как будто он попал в EOF, когда на самом деле он только что попал в этот конкретный символ.

Двигаемся дальше, atoi(&c) неверно. Если вы прочтете документацию по функции atoi — это всегда хорошая идея при использовании функций — вы обнаружите, что она ожидает строку в качестве входных данных. Однако &c не является строкой. Это адрес одного символа.

Итак, ваши варианты:

  • создать строку и передать ее atoi
  • не используйте atoi

Вы не сказали того, что ожидали; но если вы хотите преобразовать символ, который вы читаете в '3', в целое число 3, тогда вы можете написать: ther[tim][nther] = c - '0';.

Однако у вас также должен быть код для обработки случаев, когда вы читаете что-то, что не является числом.

Если вы хотите прочитать более одного символа за раз (например, "31" -> 31), то подход с использованием getc не подходит — вам нужно переключиться на использование функции, которая считывает несколько символов одновременно, например fscanf. или fgets.

Наконец, вы устанавливаете tim в 0 на каждой итерации цикла, поэтому tim++ никогда не имеет длительного эффекта, возможно, это было недосмотром.

person M.M    schedule 28.03.2014
comment
Извините, я пытаюсь прочитать число 3 и сохранить то же число в массиве. - person mrmurmanks; 28.03.2014
comment
Вы также хотите читать такие вещи, как 31 или 3.1, или весь файл состоит только из чисел от 0 до 9? - person M.M; 28.03.2014
comment
Да, он должен читать несколько чисел, но все они целые (возможно, позже он будет читать float). - person mrmurmanks; 28.03.2014
comment
Может быть, это мне поможет… while( fgets (line, sizeof(line), fp3) != NULL ) и затем внутри while я могу разделить строку. line — это указатель на некоторую строку (строку в файле). - person mrmurmanks; 28.03.2014
comment
Это был бы один из способов сделать это, да. Вы можете разделить строку, осторожно используя sscanf или strtod. - person M.M; 28.03.2014

Вы можете прочитать дубль из файла, используя fscanf. Примером может быть:

double d;
fscanf("%f", &d);

fscanf может делать гораздо больше, поэтому я рекомендую ознакомиться с документацией.

Используемый вами метод получает один символ (как указал Мэтт Макнабб - неправильно). Символ занимает 1 байт и может хранить значения от 0 до 255. Вы читаете в текстовом режиме, поскольку не указываете режим с помощью fopen (обычно считается хорошей практикой явно запрашивать либо бинарный "rb/wb" или текстовый "rt/wt" режим). Это означает, что вы прочитали значение ASCII одной цифры.

Итак, допустим, файл содержит:

7.2, 3.0, 1.0

Первый вызов getc(fp3) получит символ '7', который будет иметь значение 55 для ASCII. Очевидно, что это не даст вам то, что вы ищете.

Вместо этого вы можете использовать:

double d[3];
fscanf("%f, %f, %f" &d[0], &d[1], &d[2]);

Что бы получить три значения с плавающей запятой в файле.

person Peter Clark    schedule 28.03.2014
comment
На самом деле я стараюсь избегать fscanf, потому что не хочу хранить значения в одной строке. Но вы подали мне некоторые идеи :). - person mrmurmanks; 28.03.2014
comment
Это был просто пример, вы всегда можете читать по одному значению за раз или использовать спецификатор формата, который включает новые строки (при условии, что вы знаете, использует ли ваш файл '\n' или \r\n для новых строк). Например: fscanf("%d\n%d\n%d", ...) будет считывать одни и те же значения, если каждое из них находится в отдельной строке. Вы можете настроить спецификатор формата в соответствии с вашими потребностями. Имейте в виду, что вы также должны проверять на наличие ошибок возвращаемое значение fscanf, чтобы убедиться, что оно действительно считывает столько значений, сколько вы ожидаете. Я бы рекомендовал оставить ссылку на cstdio.h открытой, пока вы учитесь. - person Peter Clark; 28.03.2014
comment
о да, так что я могу использовать fscanf для чтения полной строки? и разделить линию позже, я полагаю. что-то вроде: fscanf (pFile, %s, str); а потом работать со строкой :) - person mrmurmanks; 28.03.2014
comment
Из документации для scanf %s спецификатора формата: любое количество непробельных символов. , останавливаясь на первом найденном символе пробела. Так что нет, %s получит только один маркер, разделенный пробелами. Если вам нужна целая строка, вам понадобится fgets. Обратите внимание, что вы можете использовать fgets и sscanf (член строки семейства scanf) вместе, чтобы получить целую строку, а затем разбить ее на токены. - person Peter Clark; 28.03.2014

person    schedule
comment
Я искал подсказку в своем коде и вспомнил ваш пост :) (довольно полезный), спасибо пикси (пикси из ace Combat?), кто знает :). Мучас грасиас desde el otro lado del pacifico pixy :D - person mrmurmanks; 20.04.2014