2014-10-08 63 views
0

如果问题实际上是愚蠢的,我很抱歉,但我刚开始学习C,并且没有人知道我能够提供帮助。 我应该统计stdin中的字母数,并说明每个字母被使用了多少次。 我们也期望使用计数器和fread方法。C程序返回意外的数字

编辑:伊戈尔帮助我与他的答案和程序现在几乎一切正确。小错误仍然存​​在:只有前10个字符被识别并计数,其他字符被忽略。输入必须大于10,否则不起作用。

我评论了我在代码中所做的更改,以便其他人可以跟踪我的错误。

我的代码是:

#include <stdio.h> 
#include <ctype.h> 

int main(){ 
    char text[10]; 
    int timesUsed[26]; // I initialized the array but didn't set the values to 0. 
    int timesUsed[26] = {0}; //this line corrected the issue with getting random numbers 
    int textLength = 0; 
    char *ptr; 
    while(fread(&text,sizeof(char),10,stdin)){ 
    ptr = &text[0];  
    while(1){ 
     if(isalpha(*ptr)){ 
    textLength++; 
    *ptr = tolower(*ptr); //the original was only tolower(*ptr); which is useless 
    timesUsed[((char) *ptr) - 'a']++; 
     } 
     if(*ptr == '\n') goto end; //the original had here only one '=' 
     /**ptr = '\0';*/ 
     if(ptr == &text[10]) goto end; // on both 
     ptr ++; 
    } 
    } 
end: 
    printf("Number of letters:%20d\n",textLength); 
    int i; 
    for(i=0;i<26;i++){ 
    if(timesUsed[i]>0){ 
     char thechar = (char) 'a' + i; 
     printf("The letter %c was used %5d time(s).\n",thechar,timesUsed[i]); 
    } 
    } 
    return 0; 
} 

哪个不打印预期的结果,它究竟是打印:

Testing testing testing testing testing testing M 
Number of letters:     9 
The letter e was used  2 time(s). 
The letter g was used  1 time(s). 
The letter i was used  1 time(s). 
The letter n was used  1 time(s). 
The letter s was used  1 time(s). 
The letter t was used  3 time(s). 

的变化进行的输出显得更有意义。尽管如此,还是有些失误

+1

从未使用goto语句,除非直到您希望C社区中的每个人都可以降低您的... – Haris 2014-10-08 17:48:34

+0

正确地格式化您的代码将有助于获得答案。我会帮忙,但我不想清理你的帖子。 – 2014-10-08 17:49:49

+0

你也期望'if(ptr =&text [10])''? – P0W 2014-10-08 17:49:56

回答

3

下次用-Wall-Wextra编译您的代码时,您会发现一些错误。

你必须初始化数组:

int timesUsed[26] = {0}; 

当你不这样做,它包含随机值和计数是不正确的。

这种说法没有任何影响:

tolower(*ptr); 

而是执行此操作:

*ptr = tolower(*ptr); 

而用C =是不一样的==它检查是否相等,所以你应该在if语句改变到:

if(*ptr == '\n') goto end; 
     /**ptr = '\0';*/ 
if(ptr == &text[10]) goto end; 
+0

非常感谢你,我会做出改变并说出它是如何发生的。 – Raeglan 2014-10-08 18:06:36

+0

我做了更改并且已经对代码进行了评论!非常感谢,只要我有15的声望,我会upvote你的答案! :) – Raeglan 2014-10-08 18:25:40

+0

没问题... :) – Igor 2014-10-08 18:28:41

0

试试这个:

#include <stdio.h> 
int main(){ 
    const char *str = "this is string to count"; 
    int counts[256] = { 0 }; 
    int i,letters=0; 
    size_t len = strlen(str); 
    for (i = 0; i < len; i++) { 
    counts[(int)(str[i])]++; 
    } 

    for (i = 0; i < 256; i++) { 
    if(counts[i]>0){ 
     printf("%c occurs %d times.\n", i , counts[i]); 
     if((char)i!=' '){ 
     letters+=counts[i]; 
     } 
    } 

    } 
printf("Number of letters : %d", letters); 
getchar(); 
    return 0; 

} 

输出:

occurs 4 times. 
c occurs 1 times. 
g occurs 1 times. 
h occurs 1 times. 
i occurs 3 times. 
n occurs 2 times. 
o occurs 2 times. 
r occurs 1 times. 
s occurs 3 times. 
t occurs 4 times. 
u occurs 1 times. 
Number of letters : 19 
0

该代码看起来太过复杂,我。这是一个全指针算术版本。没有数组符号责任:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <ctype.h> 
#include <limits.h> 

#define A ((unsigned char)'a') 
#define Z ((unsigned char)'z') 

#define BUFFER_SIZE ((size_t)8192) 

int main(int argc, char *argv[]) 
{ 
    int   counter_max = 1 + UCHAR_MAX ; 
    int   *counter  = calloc((size_t) counter_max , sizeof(int) ) ; 
    unsigned char *buffer  = calloc(BUFFER_SIZE   , sizeof(*buffer)) ; 
    int   bufl  ; 

    while ((bufl=fread(buffer,sizeof(*buffer),BUFFER_SIZE,stdin)) > 0) 
    { 
    for (unsigned char *p = buffer ; p < buffer+bufl ; ++p) 
    { 
     unsigned char c = tolower(*p) ; 
     ++ *(counter+c) ; 
    } 
    } 

    for (int *p = counter+A ; p <= counter+Z ; ++p) 
    { 
    int n = *p ; 
    if (n > 0) 
    { 
     char c = p-counter ; 
     printf("The letter '%c' was found %d times.\n" , c , n ) ; 
    } 
    } 

    return 0; 
} 
+0

它非常复杂,但我们需要使用指针,fread并从stdin获取输入。 我们还需要有一个缓冲区,并能够从标准输入变为任何大小的文本。 – Raeglan 2014-10-08 19:05:44

+0

@Raeglan,似乎是我修正的答案。 – 2014-10-08 20:28:50

1

好吧,让我们尝试改进一些东西:

#include <stdio.h> 
#include <ctype.h> 

int main(){ 
    char text[10] = ""; // This is allocating space for exactly 10 chars. 
    int timesUsed[26] = {0}; // Always initialize your variables. Particularly arrays. 
    int textLength = 0; 
    int inputLength = 0; 
    inputLength = fread(&text,sizeof(char),10,stdin); // fread returns the number of chars actually read, and since you're telling it to read 10 chars, that's the MAXIMUM amount of chars it'll read. It may read less, that's why it returns to you how much it read; 
    for(int i=0;i<inputLength;i++){ // since you know the length, iterate over it! 
     if(isalpha(text[i])){ 
     textLength++; 
     char c = tolower(text[i]); // No need to mess with pointers! 
     timesUsed[text[i] - 'a']++; 
     } 
     if(text[i] == '\n') break; //Exit the for loop. NEVER EVER EVER USE GOTO!!! Actually I don't think this will ever happen because I think fread returns when the user hits ENTER 
    } 
    printf("Number of letters:%20d\n",textLength); 
    int i; 
    for(i=0;i<26;i++){ 
    if(timesUsed[i]>0){ 
     char thechar = (char) 'a' + i; 
     printf("The letter %c was used %5d time(s).\n",thechar,timesUsed[i]); 
    } 
    } 
    return 0; 

它将可能编译罚款,但我没有检查。如果不是,可能是一些错字。 希望它有帮助。