Как прочитать целые числа и символы из текстового файла и сохранить их в отдельных массивах? - PullRequest
3 голосов
/ 04 марта 2020

Я пытаюсь читать входные данные из файла, который содержит строки, такие как «Джейн 30», «Крис 40» и т. Д., Построчно. Затем мне нужно хранить каждое имя с соответствующим номером в одном и том же индексе разных массивов, поэтому «Джейн» в одном массиве с индексом 0 и 30 в целочисленном массиве с индексом 0.

Это код Я до сих пор, но я изо всех сил пытаюсь выяснить, как извлечь целые числа в отдельный массив, а символы в другой. Пожалуйста, помогите.

#include stdio.h
#include stdlib.h
#include DarrensInfo.

int main()
{
FILE * coinfile;
coinfile = fopen("coins.txt", "r");
char names[150];
int change[50];
int x, y;

while(!feof(coinfile)){

    fgets(names, 150, coinfile);
    y = 0;

    for(x=0; names[x]; x++){

        if(names[x] <= '0' && names[x] <= '9'){

            change[y] = names[x];
            y++;

        }
    }

}

fclose(coinfile);

return 0;
}

Ответы [ 4 ]

2 голосов
/ 04 марта 2020
#define COINS_MAX_LINES 150
#define MAX_LINE_LENGTH 100  
#define MAX_NAME_LENGTH 50
int main()
{
    FILE * coinfile;
    coinfile = fopen("coins.txt", "r");
    char line[MAX_LINE_LENGTH];
    char names[COINS_MAX_LINES][MAX_NAME_LENGTH];
    int change[COINS_MAX_LINES];
    int lineno = 0;
    int i = 0;
    while(fgets(line, MAX_LINE_LENGTH, coinfile))
    {
        sscanf(line, "%s %d", names[lineno], &change[lineno]);
        ++lineno;
    }

    fclose(coinfile);

    for (i = 0; i<lineno;++i)
        printf("Name = %s Change = %d\n", names[i], change[i]);

    return 0;

}

По истечении времени l oop массив имен и массив изменений будут содержать то, что вы хотите. Я распечатал это во второй л oop

0 голосов
/ 04 марта 2020

Я пытаюсь прочитать входные данные из файла, который содержит строки, такие как «Джейн 30», «Крис 40» и т. Д., Строка за строкой

Вы читаете файл, который может содержать строки, такие как «Jane 30», «Chris 40» и т. д .; но может также содержать миллионы опечаток и / или других ошибок; и, следовательно, вам необходимо обнаружить ошибки и четко сообщить пользователю, что это за ошибка, чтобы они могли легко понять проблему, затем найти ошибку и исправить ее.

По этой причине ни один из C библиотечные функции всегда полезны.

Вместо этого постройте парсер как конечный автомат. Например (не проверено):

    // State

    int state = 0;
    int column = 0;
    int line = 1;
    char current_name[MAX_NAME_LENGTH];
    int name_length;
    int number;

    // Main loop

    for(;;) {
        int c = fgetc(file);
        column++;
        switch(state) {

        case 0:  /* At start of new line */
            if(c == FEOF) {
                return OK;
            } else if(isdigit(c)) {
                printf("ERROR: Number found at start of line (missing name), on line %d at column %d\n", line, column);
                return NOT_OK;
            } else if(isalpha(c)) {
                name_length = 0;
                current_name[name_length++] = c;
                state = 1;
            } else if(c == '\n') {
                line++
            } else if(isspace(c)) {
            } else {
                printf("ERROR: Bad character at start of line, on line %d at column %d\n", line, column);
                return NOT_OK;
            }
            break;

        case 1:  /* In middle of name */
            if(c == FEOF) {
                printf("ERROR: File ends in the middle of a name, on line %d at column %d\n", line, column);
                return NOT_OK;
            } else if(isdigit(c)) {
                printf("ERROR: No whitespace between name and number, on line %d at column %d\n", line, column);
                return NOT_OK;
            } else if(isalpha(c)) {
                if(name_length >= MAX_NAME_LENGTH) {
                    printf("ERROR: Name too long (max length is %d), on line %d at column %d\n", MAX_NAME_LENGTH, line, column);
                    return NOT_OK;
                }
                current_name[name_length++] = c;
            } else if(c == '\n') {
                printf("ERROR: No number after name, on line %d at column %d\n", line, column);
                return NOT_OK;
            } else if(isspace(c)) {
                state = 2;
            } else {
                printf("ERROR: Bad character in middle of name, on line %d at column %d\n", line, column);
                return NOT_OK;
            }
            break;

        case 2:  /* Between name and number */
            if(c == FEOF) {
                printf("ERROR: File ends after name, on line %d at column %d\n", line, column);
                return NOT_OK;
            } else if(isdigit(c)) {
                number = c - '0';
                state = 3;
            } else if(c == '\n') {
                printf("ERROR: No number after name, on line %d at column %d\n", line, column);
                return NOT_OK;
            } else if(isspace(c)) {
            } else {
                printf("ERROR: Bad character after name, on line %d at column %d\n", line, column);
                return NOT_OK;
            }
            break;

        case 4:  /* In middle of number */
            if(c == FEOF) {
                printf("ERROR: File ends in middle of number, on line %d at column %d\n", line, column);
                return NOT_OK;
            } else if(isdigit(c)) {
                if(number > INT_MAX / 10) {
                    printf("ERROR: Number is too large, on line %d at column %d\n", line, column);
                    return NOT_OK;
                }
                number *= 10;
                if(number > INT_MAX - (c - '0') ) {
                    printf("ERROR: Number is too large, on line %d at column %d\n", line, column);
                    return NOT_OK;
                }
                number += c - '0';
            } else if(c == '\n') {
                create_new_entry(current_name, name_length, number);
                line++
                state = 0;
            } else if(isspace(c)) {
                state = 5;
            } else {
                printf("ERROR: Bad character after number, on line %d at column %d\n", line, column);
                return NOT_OK;
            }
            break;

        case 5:  /* Trailing white space before end of line */
            if(c == FEOF) {
                printf("ERROR: File ends between number and end of line, on line %d at column %d\n", line, column);
                return NOT_OK;
            } else if(c == '\n') {
                line++
                create_new_entry(current_name, name_length, number);
                state = 0;
            } else if(isspace(c)) {
            } else {
                printf("ERROR: Unknown characters between number and end of line, on line %d at column %d\n", line, column);
                return NOT_OK;
            }

        }
    }
0 голосов
/ 04 марта 2020

Если вы пытаетесь разобрать имена, которые могут выглядеть как «Кинг Чарльз 3», будет сложно использовать scanf. На самом деле не так сложно делать подобные вещи без использования буферов размера stati c, и это хорошая практика для привыкания. Вам следует избегать fgets, поскольку его трудно использовать без фиксированного размера. Обратите внимание, что рост массивов общеизвестно труден, поэтому я не претендую на правильность следующего. Нужно делать это упражнение каждые несколько месяцев, чтобы напомнить, почему мы не делаем такого рода вещи в C:

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

FILE * Fopen(const char *, const char *);
void * Realloc(void *, size_t);

/* Remove trailing whitespace */
void trim_white(char *b, char *end)
{
        while( end > b && isspace(*--end)) {
                *end = '\0';
        }
}

int
main(int argc, char **argv)
{
        char *path = argc > 1 ? argv[1] : "stdin";
        FILE *coinfile = argc > 1 ? Fopen(path, "r") : stdin;
        size_t asize = 16;
        size_t bsize = 0;
        char *buf = NULL;
        char **names = Realloc(NULL, asize * sizeof *names);
        long *change = Realloc(NULL, asize * sizeof *change);
        unsigned line_number = 0;
        ssize_t char_read;
        while( buf = NULL, (char_read = getline(&buf, &bsize, coinfile)) != -1) {
                char *space;
                char *end;
                trim_white(buf, buf + char_read);
                space = strrchr(buf, ' ');
                if(space == NULL) {
                        fprintf(stderr, "Invalid input on line %d (no space)\n", line_number + 1);
                        exit(EXIT_FAILURE);
                }
                change[line_number] = strtol(space + 1, &end, 10);
                if(*end != '\0') {
                        fprintf(stderr, "Invalid input on line %d at '%s'\n", line_number + 1, space + 1);
                        exit(EXIT_FAILURE);
                }
                *space = '\0';
                names[line_number] = buf;

                if(++line_number == asize) {
                        asize *= 2;
                        names = Realloc(names, asize * sizeof *names);
                        change = Realloc(change, asize * sizeof *change);
                }
        }

        return EXIT_SUCCESS;
}

FILE *
Fopen(const char *path, const char *mode) {
        FILE *fp = fopen(path, mode);
        if( fp == NULL ) { perror(path); exit(EXIT_FAILURE); }
        return fp;
}

void *
Realloc(void *buf, size_t s)
{
        buf = realloc( buf, s );
        if( buf == NULL) { perror("realloc"); exit(EXIT_FAILURE); }
        return buf;
}
0 голосов
/ 04 марта 2020
  1. Вам нужен массив символьных массивов. Определите переменную names как names[150][30], предполагая, что длина каждого имени не будет превышать 30 символов.
  2. Используйте комбинацию fgets и fscanf для анализа строки ввода в файл в отдельные переменные по вашему желанию
#include <stdio.h>
#include <stdlib.h>

int main()
{
  FILE * coinfile;
  coinfile = fopen("coins.txt", "r");
  char names[150][30];
  int change[150];
  int x = 0, y, i;

  char buf[100];
  while(!feof(coinfile)){
    if(fgets(buf, 100, coinfile) != NULL) { 
      sscanf(buf, "%s %d", names[x], &change[x]);
      x++;
    }
  }
  fclose(coinfile);

  puts("-------");
  for (int i = 0; i < x; i++)
    printf("%s %d\n", names[i], change[i]);

  return 0;
}
...