[英]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
. 为了解析A
或2
的值,将需要两个不同的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
进行分配(无论如何您都不会重新分配),您只需声明一个结构数组即可保存从每一行读取的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++;
}
}
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
包含的每个结构输出color
和value
,您可以执行以下操作。 ( 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: 以下建议的代码:
sscanf()
fails. 正常退出或调用sscanf()
失败时,正确清理(关闭文件)。 main()
对main()
使用有效的签名 %s
so as to avoid any possibility of a buffer overflow and the resulting undefined behavior 在输入格式说明符%s
上正确使用MAX CHARACTERS修饰符,以避免任何可能的缓冲区溢出和导致的未定义行为 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
. 此外,您对colour
的malloc
有问题。 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.