[英]ASCII characters not getting printed out
我想從輸入文件中讀取卡並打印出它們的值。
但是,當我嘗試打印出字符時,它會打印出'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
處理'A'
或作為值的整數的主要問題是由於人們誤解了A
可以使用sscanf
使用"%d"
格式說明符來解析,而不能。 為什么? 當您嘗試使用"%d"
解析'A'
時, 將發生匹配失敗 ,從輸入緩沖區中不再提取任何字符,而sscanf
的返回將是失敗之前發生的成功轉換的次數。
當您擁有不同類型的數據時,例如
RED A
RED 2
為了解析A
或2
的值,將需要兩個不同的sscanf
表達式,您可以通過檢查 sscanf
的 返回值來輕松區分它們。 您有條件地執行此操作,如果使用"%s %d"
解析失敗,則嘗試使用"%s %c"
進行解析並驗證是否成功。
例如,說而不是使用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++;
}
}
上面的while
循環是用於處理從每一行讀取到buf
的信息的解析的操作代碼。 第一個sscanf
調用嘗試將解析解析為字符串和整數值。 如果返回值不是2
,則第二次調用sscanf
嘗試將內容解析為字符串和字符。 如果成功,則將字符值(例如,字符的ASCII值)分配給value
,這在您的問題中似乎是您想要的。
添加一些驗證,然后為arr
包含的每個結構輸出color
和value
,您可以執行以下操作。 ( 注意:該程序將文件名作為第一個參數讀取,或者如果未提供任何參數,則默認情況下從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;
}
( 注意:使用field-width修飾符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
仔細檢查一下,如果您還有其他問題,請告訴我。
以下建議的代碼:
sscanf()
失敗時,正確清理(關閉文件)。 main()
使用有效的簽名 %s
上正確使用MAX CHARACTERS修飾符,以避免任何可能的緩沖區溢出和導致的未定義行為 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;
}
您的代碼幾乎可以正常工作。 主要問題是您不能使用格式說明符“%s%d”來掃描“ RED A”之類的行,因為A不是整數。 相反,您可以使用char對其進行掃描。
此外,您對colour
的malloc
有問題。 需要一個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
的返回值。 例:
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.