ASCII字符未打印出来

时间:2018-12-23 00:20:14

标签: c arrays string pointers

我想从输入文件中读取卡并打印出它们的值。

但是,当我尝试打印字符时,它会打印出'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 :(得分:1)

您的主要问题是处理'A'或整数作为值,这是由于以下误解:可以使用A 格式将sscanf"%d"进行解析说明符,不能。为什么?当您尝试用'A'解析"%d"时,会发生匹配失败,则不会从输入缓冲区中提取其他字符,并且返回用于{ {1}}是失败之前成功进行转换的次数。

当您拥有不同类型的数据时,例如

sscanf

为了解析RED A RED 2 A的值,它将需要两个不同的2表达式,您可以通过检查轻松区分它们为sscanf 返回。您有条件地执行此操作,如果使用sscanf的解析失败,则尝试使用"%s %d"进行解析,并验证是否成功。

例如,说不用分配"%s %c"(无论如何也不分配),只需声明一个结构数组即可保存从各行读取的malloccolor,例如

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,以尝试将内容解析为字符串和字符。如果成功,则将字符值(例如,字符的ASCII值)分配给sscanf,这在您的问题中似乎就是您想要的。

添加一些验证,然后为value中包含的每个结构输出colorvalue,您可以执行以下操作。 (注意:该程序将文件名作为第一个参数读取,或者如果没有给出参数,则默认情况下从arr读取。不要对文件名进行硬编码。要么将文件名作为参数传递或提示其输入)

stdin

注意:使用 field-width 修饰符#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

仔细检查一下,如果还有其他问题,请告诉我。

答案 1 :(得分:0)

以下建议的代码:

  1. 不会保留每一行的内容,而只会保留当前行的内容。您可能要更改它
  2. 正确检查错误
  3. 不使用动态内存分配。您可能要更改它
  4. 干净地编译
  5. 不包括不使用那些内容的头文件
  6. 正常退出或对sscanf()的调用失败时,正确清理(关闭文件)。
  7. main()使用有效的签名
  8. 使用所有大写字母的定义值惯例
  9. 在输入格式说明符%s上正确使用MAX CHARACTERS修饰符,以避免任何可能的缓冲区溢出和未定义的行为
  10. 记录为何包含每个头文件
  11. 不能更正传入数据和对sscanf()的调用之间的不匹配强烈建议您阅读有关atoi()strtol()的信息,并修改对sscanf()的调用,以期望有两个char序列并相应保存。

现在,建议的代码:

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

答案 2 :(得分:0)

您的代码几乎可以正常工作。主要问题是您不能使用格式说明符“%s%d”来扫描“ RED A”之类的行,因为A不是整数。相反,您可以使用char对其进行扫描。

此外,您对malloc的{​​{1}}有疑问。您需要colour,因为您需要一个char指针数组。

因此,请尝试以下操作:

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