简体   繁体   English

ASCII字符未打印出来

[英]ASCII characters not getting printed out

I want to read cards from an input file and print out their values. 我想从输入文件中读取卡并打印出它们的值。

However when I try to print out characters it prints out '0' . 但是,当我尝试打印出字符时,它会打印出'0'

If I print out the character 'A' , then normally the int value 65 is supposed to be printed out since I stored the character 'A' as an Int. 如果我打印出字符'A' ,则通常应该打印出int值65 ,因为我将字符'A'存储为Int。

Could anyone help me out? 有人可以帮我吗?

Thank you in advance. 先感谢您。

#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;
}

input: 输入:

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

Your primary problem handling either 'A' or an integer as the value, stems from the misunderstanding that A can be parsed with sscanf using the "%d" format specifier , it can't. 处理'A'或作为值的整数的主要问题是由于人们误解了A可以使用sscanf使用"%d" 格式说明符来解析,而不能。 Why? 为什么? When you attempt to parse 'A' with "%d" a matching failure occurs, no further characters are extracted from the input buffer, and the return for sscanf will be the number of successful conversions that took place prior to the failure. 当您尝试使用"%d"解析'A'时, 发生匹配失败 ,从输入缓冲区中不再提取任何字符,而sscanf返回将是失败之前发生的成功转换的次数。

When you have data of differing types, eg 当您拥有不同类型的数据时,例如

RED A
RED 2

In order to parse the values for A or 2 , it will require two different sscanf expressions, which you can easily distinguish simply by checking the return for sscanf . 为了解析A2的值,将需要两个不同的sscanf表达式,您可以通过检查 sscanf 返回值来轻松区分它们。 You do this in a conditional and if parsing with "%s %d" fails, you attempt the parse with "%s %c" and validate whether that succeeded. 您有条件地执行此操作,如果使用"%s %d"解析失败,则尝试使用"%s %c"进行解析并验证是否成功。

For instance, say instead of allocating with malloc (you are not reallocating anyway), you simply declare an array of struct to hold the color and value read from each line, eg 例如,说而不是使用malloc进行分配(无论如何您都不会重新分配),您只需声明一个结构数组即可保存从每一行读取的colorvalue ,例如

...
#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++;
        }
    }

The while loop above being the operative code for handling the parse of information read from each line into buf . 上面的while循环是用于处理从每一行读取到buf的信息的解析的操作代码。 The first sscanf call attempts the parse into a string and integer value. 第一个sscanf调用尝试将解析解析为字符串和整数值。 If the return is not 2 , then a second call to sscanf is made to attempt to parse the contents into a string and a character. 如果返回值不是2 ,则第二次调用sscanf尝试将内容解析为字符串和字符。 If that succeeds, the character value (eg the ASCII value for the character) is assigned to value , which from your question appears to be what you intended. 如果成功,则将字符值(例如,字符的ASCII值)分配给value ,这在您的问题中似乎是您想要的。

Adding a few validations and then outputting the color and value for each struct contained in arr , you could do something like the following. 添加一些验证,然后为arr包含的每个结构输出colorvalue ,您可以执行以下操作。 ( note: the program takes the filename to read as the first argument or reads from stdin by default if no argument is given. Don't hardcode filenames. Either pass the filename as an argument or prompt for its entry) 注意:该程序将文件名作为第一个参数读取,或者如果未提供任何参数,则默认情况下从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;
}

( note: the use of the field-width modifier 13 to protect the character array bounds for color ) 注意:使用field-width修饰符13保护color的字符数组边界)

Example Use/Output 使用/输出示例

Using your data as input would result in the following: 将您的数据用作输入将导致以下结果:

$ ./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

Look things over and let me know if you have further questions. 仔细检查一下,如果您还有其他问题,请告诉我。

the following proposed code: 以下建议的代码:

  1. does not keep the contents of every line, rather only of the current line. 不保留每一行的内容,而仅保留当前行的内容。 You might want to change that 您可能要更改
  2. properly checks for errors 正确检查错误
  3. does not use dynamic memory allocation. 不使用动态内存分配。 You might want to change that 您可能要更改
  4. cleanly compiles 干净地编译
  5. Does not include header files those contents are not used 不包括头文件,不使用那些内容
  6. Properly cleans up (closes files) when exiting either normally or when a call to sscanf() fails. 正常退出或调用sscanf()失败时,正确清理(关闭文件)。
  7. uses a valid signature for main() main()使用有效的签名
  8. uses the convention of defined values being in all capitals 使用所有大写字母的定义值惯例
  9. properly uses MAX CHARACTERS modifier on the input format specifier %s so as to avoid any possibility of a buffer overflow and the resulting undefined behavior 在输入格式说明符%s上正确使用MAX CHARACTERS修饰符,以避免任何可能的缓冲区溢出和导致的未定义行为
  10. documents why each header file is being included 说明为什么要包含每个头文件
  11. does NOT correct the mismatch between the incoming data and the call to sscanf() Strongly suggest you read about atoi() and strtol() and modify the call to sscanf() to expect two char sequences and save them accordingly. 不能纠正传入数据和对sscanf()的调用之间的不匹配,强烈建议您阅读有关atoi()strtol()并修改对sscanf()的调用,以期获得两个字符序列并相应地保存它们。

And now, the proposed code: 现在,建议的代码:

#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;
}

Your code is pretty close to something that works. 您的代码几乎可以正常工作。 The main problem is that you can not scan a line like "RED A" using the format specifier "%s %d" as A is not an integer. 主要问题是您不能使用格式说明符“%s%d”来扫描“ RED A”之类的行,因为A不是整数。 Instead you can scan it using a char. 相反,您可以使用char对其进行扫描。

Further you have a problem with the malloc of colour . 此外,您对colourmalloc有问题。 You need to do sizeof(char*) as you want an array of char pointers. 需要一个char指针数组时,需要执行sizeof(char*)

So try something like: 因此,尝试类似:

#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;
}

Output: 输出:

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)

Also notice that you should always check the return value of malloc . 还要注意,您应该始终检查malloc的返回值。 Example: 例:

SomeType *someVar = malloc(sizeof(SomeType));  // or better malloc(sizeof *momeVar);
if (someVar == NULL)
{
    // Out of memory - add error handling (e.g. terminate program)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM