Как я могу прочитать два столбца чисел в текстовом файле? - PullRequest
0 голосов
/ 19 января 2020

Мой .txt выглядит так, например:

1.0 2.0

1.0 1.0

2.0 3.0

2.0 1.0

Я хочу запустить этот файл, используя каждую строку, когда это необходимо. Чтобы объяснить, у меня есть уравнение (L = Ax + B), которое мне нужно рассчитать для разных х. Есть ли способ прочитать каждую строку в файле отдельно, взяв A и B в этой строке. Таким образом, первый член L будет использовать первые A и B.

Я не делал этого раньше. Это то, что я уже знаю:

void coefficients(double *A, double *B) {
    FILE *infile;

    if(2!=fscanf(infile,"%lf %lf",A, B)) {
        printf("Error reading parameters from file\n");
        exit(1);

    }
    fclose(infile);
}

И затем вызывая это в int_main:

    double A;
    double B;
    // Read in from file; 
    coefficients(&A, &B);

Ответы [ 3 ]

0 голосов
/ 19 января 2020

Имея файл с потенциальными пустыми строками и потенциальными строками, которые содержат что-то отличное от пары double значений, которые вы ищете, вы гораздо лучше читаете каждую строку в буфер и анализируете нужные значения из буфера с sscanf вместо того, чтобы пытаться читать напрямую с fscanf. Таким образом, строка ввода расходуется при каждом чтении, и вам не нужно беспокоиться о том, что остается в вашем входном потоке, в зависимости от используемых спецификаторов преобразования.

Далее, чтобы прочитать несколько значений в A и B, оба A и B должны быть массивами double (или выделенным блоком памяти, который может содержать несколько значений double)

Например, в main() может объявите:

#include <stdio.h>

#define MAXC 1024   /* if you need a constant, #define one (or more) */
...
int main (int argc, char **argv) {

    double a[MAXC] = {0}, b[MAXC] = {0};    /* arrays of MAXC doubles */

Теперь у вас есть хранилище для 1024 двойных значений. Ваша функция coefficient, которая читает значения double, должна возвращать количество прочитанных значений. Он также должен принимать открытый и проверенный поток FILE* в качестве параметра. (если файл не может быть открыт в проверенном в вызывающей программе - нет причин вызывать функцию, чтобы попытаться начать чтение с начала)

Собрав все вместе, вы можете сделать:

size_t coefficients (FILE *fp, double *a, double *b)
{
    char buf[MAXC];         /* buffer for reading each line */ 
    size_t ncoeff = 0;      /* number of coefficient pairs read */

    while (ncoeff < MAXC && fgets (buf, MAXC, fp))  /* read each line */
        /* if it contains 2 double values */
        if (sscanf (buf, "%lf %lf", &a[ncoeff], &b[ncoeff]) == 2)
            ncoeff++;       /* increment counter */

    return ncoeff;          /* return total count of pairs read */
}

Короткий пример, в целом, вы могли бы получить:

#include <stdio.h>

#define MAXC 1024   /* if you need a constant, #define one (or more) */

size_t coefficients (FILE *fp, double *a, double *b)
{
    char buf[MAXC];         /* buffer for reading each line */ 
    size_t ncoeff = 0;      /* number of coefficient pairs read */

    while (ncoeff < MAXC && fgets (buf, MAXC, fp))  /* read each line */
        /* if it contains 2 double values */
        if (sscanf (buf, "%lf %lf", &a[ncoeff], &b[ncoeff]) == 2)
            ncoeff++;       /* increment counter */

    return ncoeff;          /* return total count of pairs read */
}

int main (int argc, char **argv) {

    double a[MAXC] = {0}, b[MAXC] = {0};    /* arrays of MAXC doubles */
    size_t n = 0;                           /* count of doubles returned */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    if (!(n = coefficients (fp, a, b))) {   /* validate coeff pairs read */
        fputs ("error: no double values read from file.\n", stderr);
        return 1;
    }

    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);

    for (size_t i = 0; i < n; i++)  /* output coefficients */
        printf ("a[%zu] : %.1f   b[%zu] : %.1f\n", i, a[i], i, b[i]);
}

(при необходимости вы можете настроить размер массивов)

Пример входного файла

$ cat dat/coeffpairs.txt
    A B

    1.0 2.0

    1.0 1.0

    2.0 3.0

    2.0 1.0

Пример использования / Вывод

$ ./bin/readcoeff dat/coeffpairs.txt
a[0] : 1.0   b[0] : 2.0
a[1] : 1.0   b[1] : 1.0
a[2] : 2.0   b[2] : 3.0
a[3] : 2.0   b[3] : 1.0

Просмотрите все и дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 21 января 2020

Это зависит от того, что вы хотите сделать. Если вы просто хотите прочитать данные и не заботитесь о том, что происходит, когда они не в форме двух столбцов, вы можете просто прочитать их с помощью fscanf в al oop:

double  A, B;
while(fscanf(fp, "%ld%ld", &A, &B) == 2) {
    // do something with A and B

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

Если, с другой стороны, вы хотите убедиться, что в каждой строке два числа и нет пустых строк, вы можете использовать fgets + sscanf :

char line[256];    
while (fgets(line, sizeof line, fp)) {
    double A, B;
    int end;
    if (sscanf(line, "%ld%ld %n", &A, &B, &len) == 2 && line[end] == 0) {
        // got a line with (just) a pair of numbers
    } else {
        fprintf(stderr, "malformed input line: %s", line);
    }
}

Если вы также хотите проверить, что числа выстроены в столбцы, это немного сложнее. Вы можете легко проверить наличие выровненных по левому или правому краю столбцов

char line[256];
int a_col = -1, b_col = -1, lineno = 0;    
while (fgets(line, sizeof line, fp)) {
    double A, B;
    int a_right, b_right, end;
    ++lineno;
    if (sscanf(line, "%ld%n%ld%n %n", &A, &a_right, &B, &b_right, &len) == 2 && line[end] == 0) {
        // got a line with (just) a pair of numbers
        if (a_col >= 0 && (a_col != a_right || b_col != b_right)) {
            fprintf(stderr, "columns on line %d not lined up with previous line\n", lineno);
        }
        a_col = a_right;
        b_col = b_right;
    } else {
        fprintf(stderr, "malformed input on line %d", lineno);
    }
}
0 голосов
/ 19 января 2020

Вы можете использовать этот метод для считывания текстового файла (file.txt) в массив символов (buffer) построчно, используя fgets(), а затем проанализируйте его с помощью * 1006. * чтобы найти в нем двойное значение.

Код

double a=0;
double b=0;

int bufferLength = 1024;
char buffer[bufferLength];

FILE *fp = fopen("file.txt", "r");
if (!fp){
    printf("Cant open file\n");
    return -1;
}

while(fgets(buffer, bufferLength, fp)) {
    //printf("%s\n", buffer);   
    if (2==sscanf(buffer, "%lf %lf", &a,&b)){
        printf("a: %f   b: %f\n", a,b);
    }
}

fclose(fp);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...