Символы ASCII не распечатываются - PullRequest
0 голосов
/ 23 декабря 2018

Я хочу прочитать карточки из входного файла и распечатать их значения.

Однако, когда я пытаюсь распечатать символы, он печатает '0'.

Если я распечатываюсимвол 'A', тогда обычно предполагается вывод значения int 65, поскольку я сохранил символ 'A' как Int.

Может ли кто-нибудь мне помочь?

СпасибоВы заранее.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max 100
#define MAX_LENGTH 14

int main(){
  char *lines = malloc(max*sizeof(char));

    char **colour = malloc(max*sizeof(char));
    int *value =malloc(max*sizeof(int));
    FILE *fp;
    fp = fopen("config2.txt", "r");
    if(fp == NULL){
        printf("Cannot open filelist.txt\n");
        return 1;
    }
    int i= 0;
    while (i < max && fgets(lines, MAX_LENGTH, fp) != NULL) { 
        colour[i] = malloc(MAX_LENGTH); 
        sscanf(lines, "%s %d", colour[i], &value[i]);
        printf("%s\n", colour[i]);
        printf("%d\n", value[i]);

        i++;
    }
    return 0;
}

Ввод:

RED A
RED 2
RED 3
RED 4
RED 5
RED 6
RED 7
RED 8
RED 9
RED 10
RED J
RED Q
RED K

Ответы [ 3 ]

0 голосов
/ 23 декабря 2018

Ваш код довольно близок к тому, что работает.Основная проблема заключается в том, что вы можете , а не сканировать строку типа «КРАСНЫЙ А», используя спецификатор формата «% s% d», так как А не является целым числом.Вместо этого вы можете отсканировать его, используя символ.

Кроме того, у вас проблема с malloc из colour.Вам нужно сделать sizeof(char*) так, как вам нужен массив указателей на символы.

Так что попробуйте что-то вроде:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max 100
#define MAX_LENGTH 14

int main(){
  char *filename = "config2.txt";
  char *lines = malloc(max*sizeof(char));
  char **colour = malloc(max*sizeof(char*));  // Use sizeof(char*)
  char *value =malloc(max*sizeof(char));      // Use char instead of int
  FILE *fp;

  fp = fopen(filename, "r");
  if(fp == NULL){
    fprintf(stderr, "Cannot open %s : ", filename);
    perror("");
    exit(1);
  }

  int i= 0;
  while (i < max && fgets(lines, MAX_LENGTH, fp) != NULL) {
    colour[i] = malloc(MAX_LENGTH);
    if (sscanf(lines, "%s %c", colour[i], &value[i]) != 2)  // Use %c instead of %d and check return value
    {
      printf("Unexpected input file data\n");
      exit(1);
    }
    printf("%s ", colour[i]);
    printf("%c (%d)\n", value[i], value[i]);       // Print value as both char and int

    i++;
  }

  // Clean up
  fclose (fp);
  for (int j = 0; j<i; ++j) free(colour[j]);
  free(colour);
  free(value);

  return 0;
}

Вывод:

RED A (65)
RED 2 (50)
RED 3 (51)
RED 4 (52)
RED 5 (53)
RED 6 (54)
RED 7 (55)
RED 8 (56)
RED 9 (57)
RED 1 (49)
RED J (74)
RED Q (81)
RED K (75)

Также обратите внимание, чтоВы всегда должны проверять возвращаемое значение malloc.Пример:

SomeType *someVar = malloc(sizeof(SomeType));  // or better malloc(sizeof *momeVar);
if (someVar == NULL)
{
    // Out of memory - add error handling (e.g. terminate program)
}
0 голосов
/ 23 декабря 2018

Ваша основная проблема, связанная с 'A' или целым числом в качестве значения, связана с неправильным пониманием того, что A может быть проанализирован с sscanf с использованием спецификатора формата "%d" , он может 'т.Зачем?Когда вы пытаетесь выполнить синтаксический анализ 'A' с "%d" a , происходит сбой сопоставления , дальнейшие символы не извлекаются из буфера ввода, и return для sscanf будет числомуспешных преобразований, имевших место до сбоя.

Если у вас есть данные разных типов, например

RED A
RED 2

Для анализа значений для A или 2,для этого потребуются два различных выражения sscanf, которые можно легко различить, просто проверив return для sscanf.Вы делаете это в условном выражении, и если синтаксический анализ с "%s %d" завершается неудачно, вы пытаетесь выполнить анализ с помощью "%s %c" и проверяете, успешно ли это произошло.

Например, скажем, вместо выделения с помощью malloc (вы неперераспределение в любом случае), вы просто объявляете массив struct для хранения color и value чтения из каждой строки, например,

...
#define MAXCOLR   14
#define MAXLINE  100
#define MAXCHR  1024    /* don't skimp on read buffer size */

typedef struct {        /* simple struct to associate each color/value */
    char color[MAXCOLR];
    int value;
} colorval_t;

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

    size_t ndx = 0;     /* index */
    char buf[MAXCHR];   /* read buffer */
    colorval_t arr[MAXLINE] = {{ .color = "" }};    /* array of struct */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    ...
    while (ndx < MAXLINE && fgets (buf, MAXCHR, fp)) {
        char c;     /* temp char to use for parsing 2nd case */
        if (sscanf (buf, "%13s %d", arr[ndx].color, &arr[ndx].value) == 2)
            ndx++;
        else if (sscanf (buf, "%13s %c", arr[ndx].color, &c) == 2) {
            arr[ndx].value = c;
            ndx++;
        }
    }

Цикл while выше является рабочим кодом для обработки анализаинформации, прочитанной из каждой строки в buf.Первый вызов sscanf пытается проанализировать строку и целочисленное значение.Если возвращаемое значение не равно 2, то выполняется второй вызов sscanf, чтобы попытаться проанализировать содержимое в строку и символ.Если это удастся, символьному значению (например, значению ASCII для символа) присваивается значение value, которое, по вашему вопросу, соответствует вашему.

Добавление нескольких проверок и вывод color и value для каждой структуры, содержащейся в arr, вы можете сделать что-то вроде следующего.( примечание: программа берет имя файла для чтения в качестве первого аргумента или читает из stdin по умолчанию, если аргумент не указан. Не указывайте имена файлов жестко. Либо передайте имя файла в качестве аргумента, либо запроситеего запись)

#include <stdio.h>

#define MAXCOLR   14
#define MAXLINE  100
#define MAXCHR  1024    /* don't skimp on read buffer size */

typedef struct {
    char color[MAXCOLR];
    int value;
} colorval_t;

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

    size_t ndx = 0;
    char buf[MAXCHR];
    colorval_t arr[MAXLINE] = {{ .color = "" }};
    /* 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;
    }

    while (ndx < MAXLINE && fgets (buf, MAXCHR, fp)) {
        char c;
        if (sscanf (buf, "%13s %d", arr[ndx].color, &arr[ndx].value) == 2)
            ndx++;
        else if (sscanf (buf, "%13s %c", arr[ndx].color, &c) == 2) {
            arr[ndx].value = c;
            ndx++;
        }
    }
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    for (size_t i = 0; i < ndx; i++)
        printf ("arr[%2zu] : %-14s %d\n", i, arr[i].color, arr[i].value);

    return 0;
}

( примечание: использование модификатора ширина поля 13 для защиты границ массива символов для color)

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

Использование ваших данных в качестве входных данных приведет к следующему:

$ ./bin/rdcolorval <dat/colorval.txt
arr[ 0] : RED            65
arr[ 1] : RED            2
arr[ 2] : RED            3
arr[ 3] : RED            4
arr[ 4] : RED            5
arr[ 5] : RED            6
arr[ 6] : RED            7
arr[ 7] : RED            8
arr[ 8] : RED            9
arr[ 9] : RED            10
arr[10] : RED            74
arr[11] : RED            81
arr[12] : RED            75

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

0 голосов
/ 23 декабря 2018

следующий предложенный код:

  1. не сохраняет содержимое каждой строки, а только текущей строки.Возможно, вы захотите изменить, чтобы
  2. правильно проверял наличие ошибок
  3. не использует динамическое выделение памяти.Возможно, вы захотите изменить это
  4. безупречной компиляции
  5. Не включает заголовочные файлы, содержимое которых не используется
  6. Правильно очищает (закрывает файлы) при выходе из системы либо нормально, либо когдавызов sscanf() завершается неудачно.
  7. использует действительную подпись для main()
  8. использует соглашение об определенных значениях во всех столицах
  9. правильно использует модификатор MAX CHARACTERS наспецификатор формата ввода %s, чтобы избежать какой-либо возможности переполнения буфера и результирующего неопределенного поведения
  10. указывает, почему каждый заголовочный файл включается
  11. НЕ исправляет несоответствие между входящими даннымии вызов sscanf() Настоятельно рекомендуем вам прочитать о atoi() и strtol() и изменить вызов на sscanf(), чтобы ожидать две последовательности символов и соответственно сохранить их.

А теперь предложенный код:

#include <stdio.h>   // printf(), fprintf(), sscanf()
#include <stdlib.h>  // exit(), EXIT_FAILURE


//#define MAX_LINES 100
#define MAX_LENGTH 14


int main( void )
{
    char lines[ MAX_LENGTH +1];
    char colour[ MAX_LENGTH ];

    int  value;

    FILE *fp = fopen( "config2.txt", "r" );
    if(fp == NULL)
    {
        perror( "fopen to read config2.txt failed" );
        exit( EXIT_FAILURE );
    }


    while ( fgets( lines, MAX_LENGTH, fp ) ) 
    {   
        if( sscanf(lines, "%100s %d", colour, &value) != 2 )
        {
            fprintf( stderr,  "sscanf to extract two fields from input line failed\n" );
            fclose( fp );
            exit( EXIT_FAILURE );
        }

        printf( "colour: %s\n", colour );
        printf( "value:  %d\n", value );
    }
    fclose( fp );
    return 0;
}
...