我困惑于将txt文件提供给我的可执行程序的情况。

huangapple go评论64阅读模式
英文:

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

  1. 使用符号常量 LEN 而不是硬编码魔术值,尤其在需要在两个地方使用相同变量时。

  2. (未修复) 考虑使用 unsigned 类型(如 unsignedsize_t)而不是有符号的 int 用于 myAsciiList,这样更能准确表示正数计数的意图。

  3. 如果 char 是有符号的,它的行为是实现定义的。如果它是有符号的,负值将导致缓冲区下溢。您还假定小于 128,否则会导致缓冲区溢出。

  4. 在循环之前和循环中有相同的代码,这可能是一个错误。此外,在循环之前您没有实现错误处理,这可能会有问题(如果它起作用的话)。消除重复的代码是个好主意。在这种情况下,我可以直接删除它,其他情况下可以将重复的代码移到一个函数中,然后根据需要多次调用该函数。

  5. scanf() 返回 EOF。它不会将变量 gettingChar 设置为 EOF

  6. 如果要输出内容,您需要打印一些东西。

  7. 尽量在可能的情况下减少变量的数量和作用域。char ch; 现在在使用之前声明。myIndex 被消除,因为它的值与 ch 相同,下面在需要时将其强制转换为无符号值。

  8. (未修复) 考虑在打印结果时对非可打印字符(如空格、换行符或制表符)进行特殊处理。

您可能希望按照以下方式进行修改代码:

#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
英文:
  1. Use symbolic constants LEN instead hard-coding magic values. Especially when you need use the same variable in two places.

  2. (Not fixed) Consider using a unsigned type (like unsigned or size_t) instead of (signed) int for myAsciiList. This better captures the intend of positive counts.

  3. It's implementation defined if char is signed or unsigned. 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.

  4. 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.

  5. scanf() returns EOF. It does not set the variable gettingChar to it.

  6. You need to print something if you want output.

  7. 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 as ch and below I cast it to an unsigned value when needed.

  8. (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 &lt;stdio.h&gt;

#define LEN 128

int main() {
	int myAsciiList[LEN] = {0};
	for(;;) {
		char ch;
		int rv = scanf(&quot;%c&quot;, &amp;ch);
		if(rv == EOF)
			break;
		if(!rv) {
			printf(&quot;scanf failed\n&quot;);
			break;
		}
		if((unsigned) ch &gt;= LEN) {
			printf(&quot;ch is too large\n&quot;);
			break;
		}
		myAsciiList[(unsigned) ch]++;
	}
	for(size_t i = 0; i &lt; LEN; i++) {
		if(myAsciiList[i])
			printf(&quot;%c: %d\n&quot;, (char) i, myAsciiList[i]);
	}
}

and here is an example run with the source file as input:

$ ./count &lt; count.c
        : 41

: 26
 : 38
!: 1
&quot;: 8
#: 2
%: 3
&amp;: 1
(: 14
): 14
+: 4
,: 3
.: 1
0: 2
1: 1
2: 1
8: 1
:: 1
;: 14
&lt;: 2
=: 6
&gt;: 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

huangapple
  • 本文由 发表于 2023年5月7日 14:19:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76192464.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定