英文:
I am confusing of my C program in the case of giving a txt file to my executable program
问题
I cannot assist with code-related tasks.
英文:
I wanna count numbers of every Ascii characters from text file. So I prgrammed my C file that can read text file. Here is my C source code.
#include <stdio.h>
int main()
{
/*c언어 소스파일을 컴파일 한 뒤 ./{실행파일명}<{넣어줄 파일명}으로 터미널에 입력하면 파일의 내용이 input으로 들어간다.
어떠한 자료구조에 넣어주는 것이 효율적일 것인가? ==> 그냥 무식하게 하나하나 다 세는 방법도 있긴 함.
*/
int myAsciiList[128]={0,};//나올 때마다 더해줄 아스키 코드임.
char gettingChar;//매번 입력받을 것을 말한다.
scanf("%c",&gettingChar);//먼저 파일로부터 문자를 하나 입력 받는다.
int myIndex;
myIndex=gettingChar;
myAsciiList[myIndex]++;
while(1)//계속해서 입력을 받아들인다.
{
scanf("%c",&gettingChar);
if(gettingChar==EOF) break;
else{
myIndex=gettingChar;
myAsciiList[myIndex]++;
}
}
return 0;
}
I compiled my C source code by using Visual Studio Code and made executable file. And then I gave my text file in terminal with command "./count < input.txt".</br>
But my terminal does not show me anything. Like this,</br>
MacBookAir ~/Desktop/2023_Algorithm/hw4 main ± ./count < test.txt
</br>
Can you recommend me how to fix my code?😂
答案1
得分: 3
-
使用符号常量
LEN
而不是硬编码魔术值,尤其在需要在两个地方使用相同变量时。 -
(未修复) 考虑使用
unsigned
类型(如unsigned
或size_t
)而不是有符号的int
用于myAsciiList
,这样更能准确表示正数计数的意图。 -
如果
char
是有符号的,它的行为是实现定义的。如果它是有符号的,负值将导致缓冲区下溢。您还假定小于 128,否则会导致缓冲区溢出。 -
在循环之前和循环中有相同的代码,这可能是一个错误。此外,在循环之前您没有实现错误处理,这可能会有问题(如果它起作用的话)。消除重复的代码是个好主意。在这种情况下,我可以直接删除它,其他情况下可以将重复的代码移到一个函数中,然后根据需要多次调用该函数。
-
scanf()
返回EOF
。它不会将变量gettingChar
设置为EOF
。 -
如果要输出内容,您需要打印一些东西。
-
尽量在可能的情况下减少变量的数量和作用域。
char ch;
现在在使用之前声明。myIndex
被消除,因为它的值与ch
相同,下面在需要时将其强制转换为无符号值。 -
(未修复) 考虑在打印结果时对非可打印字符(如空格、换行符或制表符)进行特殊处理。
您可能希望按照以下方式进行修改代码:
#include <stdio.h>
#define LEN 128
int main() {
int myAsciiList[LEN] = {0};
for(;;) {
char ch;
int rv = scanf("%c", &ch);
if(rv == EOF)
break;
if(!rv) {
printf("scanf failed\n");
break;
}
if((unsigned) ch >= LEN) {
printf("ch is too large\n");
break;
}
myAsciiList[(unsigned) ch]++;
}
for(size_t i = 0; i < LEN; i++) {
if(myAsciiList[i])
printf("%c: %d\n", (char) i, myAsciiList[i]);
}
}
以下是使用源文件作为输入的示例运行:
$ ./count < count.c
: 41
: 26
: 38
!: 1
": 8
#: 2
%: 3
&: 1
(: 14
): 14
+: 4
,: 3
.: 1
0: 2
1: 1
2: 1
8: 1
:: 1
;: 14
<: 2
=: 6
>: 2
A: 4
E: 5
F: 1
L: 8
N: 4
O: 1
[: 4
\: 3
]: 4
_: 1
a: 10
b: 3
c: 16
d: 7
e: 11
f: 13
g: 3
h: 8
i: 37
k: 3
l: 3
m: 5
n: 18
o: 5
p: 3
r: 14
s: 15
t: 13
u: 3
v: 3
y: 4
z: 1
{: 6
}: 6
英文:
-
Use symbolic constants
LEN
instead hard-coding magic values. Especially when you need use the same variable in two places. -
(Not fixed) Consider using a
unsigned
type (likeunsigned
orsize_t
) instead of (signed)int
formyAsciiList
. This better captures the intend of positive counts. -
It's implementation defined if
char
issigned
orunsigned
. If it's signed, a negative value will cause a buffer underflow. You also assume that the less than 128 otherwise it would cause a buffer overflow. -
You have the same code before the loop as in it. This is probably a mistake. Also, before the loop you don't implement error handling which is problematic (if it worked). It's a good idea to eliminate duplicate code. In this case I could just remove it, other times to move duplicate code into a function and call it the function as many times as needed instead.
-
scanf()
returnsEOF
. It does not set the variablegettingChar
to it. -
You need to print something if you want output.
-
Minimize number and scope of variables whenever possible.
char ch;
is now declared just before it's use.myIndex
was eliminated as it's was the same value asch
and below I cast it to an unsigned value when needed. -
(Not fixed) Consider special handling of non-printable characters like space, newline or tab when you print out the result.
You probably want something along these lines:
#include <stdio.h>
#define LEN 128
int main() {
int myAsciiList[LEN] = {0};
for(;;) {
char ch;
int rv = scanf("%c", &ch);
if(rv == EOF)
break;
if(!rv) {
printf("scanf failed\n");
break;
}
if((unsigned) ch >= LEN) {
printf("ch is too large\n");
break;
}
myAsciiList[(unsigned) ch]++;
}
for(size_t i = 0; i < LEN; i++) {
if(myAsciiList[i])
printf("%c: %d\n", (char) i, myAsciiList[i]);
}
}
and here is an example run with the source file as input:
$ ./count < count.c
: 41
: 26
: 38
!: 1
": 8
#: 2
%: 3
&: 1
(: 14
): 14
+: 4
,: 3
.: 1
0: 2
1: 1
2: 1
8: 1
:: 1
;: 14
<: 2
=: 6
>: 2
A: 4
E: 5
F: 1
L: 8
N: 4
O: 1
[: 4
\: 3
]: 4
_: 1
a: 10
b: 3
c: 16
d: 7
e: 11
f: 13
g: 3
h: 8
i: 37
k: 3
l: 3
m: 5
n: 18
o: 5
p: 3
r: 14
s: 15
t: 13
u: 3
v: 3
y: 4
z: 1
{: 6
}: 6
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论