[英]Getting random increment while trying to count no of uppercase letters in C
我正在嘗試從輸入中找到無大小寫字符。
這是我的代碼:
#include <stdio.h>
#include <string.h>
int main()
{
char cAFirst[25];
int k = 0,uc =0 ,lc =0 ;
fgets(cAFirst,25,stdin);
// printf("out: %d \n",k);
for (size_t i = 0; i < 25; i++) {
k = (int)cAFirst[i];
if ((k <= 90) && (k >= 65)) {
uc++;
}
if ((k >= 97) && (k <= 122)) {
lc++;
}
}
printf("Uppercase Letters=%i \nLowercase Letters=%i \n",uc,lc );
return 0;
}
小寫字母( lc
)可以,但是uc
值是隨機增加的。
我已經嘗試過更改printf的格式,並且有時可以工作,但是問題是我必須使用上面給出的相同格式來提交此代碼。
而是總是迭代25次,直到檢測到輸入結束為止。
// for (size_t i = 0; i < 25; i++) {
for (size_t i = 0; cAFirst[i]; i++) { // detect null character.
考慮到OP的已發布代碼中的以下代碼段:
char cAFirst[25]; // <- Uninitialized, the contents are indeterminated
// ...
fgets(cAFirst,25,stdin); // <- We don't know if it succeeded or not
// ...
for (size_t i = 0; i < 25; i++) {
// ... ^^^^^^
}
它將最多24個字符從stdin
復制到數組(包括換行符,如果存在的話),還添加了null終止符(如果沒有發生流錯誤),但是當執行循環時,它將遍歷所有25個字符數組,即使輸入的字符串較短,也要考慮具有不確定值的字符。
為了避免這種情況,我們只需要通過對字符進行計數或使用空終止符作為標記來測試僅從輸入流實際讀取的字符。
我們可以將數組初始化為零(零),也可以避免使用重復的幻數,這很容易出錯。
#include <stdio.h>
// I'd use a bigger value, like 256, but OP's use case is not specified.
enum {
BUF_SIZE = 25
};
int main(void)
{
// All the elements of the array are set to zero, not only the first.
char buf[BUF_SIZE] = {'\0'};
// ...
現在,即使在上一個循環中測試了數組中的所有字符,也不會出現虛假值,並且統計信息將保持一致。 但是,這不是一個真正的解決方案,盡管通常建議在使用所有變量之前先對其進行初始化,但在這種情況下沒有必要。
正如chux指出的那樣,應該檢查fgets
之類的函數的返回值,以驗證操作是否成功以及我們的變量處於有效狀態。
if ( fgets(buf, BUF_SIZE, stdin) == NULL ) {
if (feof(stdin)) {
fprintf(stderr, "Abnormal end of input.\n");
// The contents of the array are not altered
}
if (ferror(stdin)) {
fprintf(stderr, "A stream error occurred.\n");
// The contents of the array are indeterminated, maybe not even null-terminated
}
exit(EXIT_FAILURE);
}
關鍵是要確保在此調用之后,該數組以空值終止。 甚至像下面這樣的檢查也足夠:
if ( fgets(buf, BUF_SIZE, stdin) == NULL ) {
fprintf(stderr, "An error occurred while reading from stdin.\n");
buf[0] = '\0';
// Continues the program despite the error, but with a valid (empty) string
}
值得記住的是,除了讀取的字符外,其他任何字符都保留在輸入流中。
現在我們有了一個有效的(以null結尾的)數組,我們可以遍歷它:
int uc = 0, lc = 0;
for (size_t i = 0; buf[i] != '\0'; i++) {
// which can also be written as 'for (size_t i = 0; buf[i]; i++) {'
// It's also more readable without magic numbers:
if ( 'A' <= buf[i] && buf[i] <= 'Z' ) {
uc++;
}
else if ( 'a' <= buf[i] && buf[i] <= 'z' ) {
lc++;
}
}
printf("Uppercase Letters = %i\nLowercase Letters = %i\n", uc, lc);
return EXIT_SUCCESS;
}
上一個代碼段可以使用頭文件<ctype.h>
定義的isupper
和islower
類的功能從ASCII代碼進行概括。 同樣,字符串的實際長度可用於限制for循環:
// Length of the maximum initial segment of the array, that consists of
// only the characters not equal to a newline or null character
size_t length = strcspn(buf, "\n");
int uc = 0, lc = 0;
for (size_t i = 0; i < length; i++) {
unsigned char k = buf[i];
if ( isupper(k) ) {
uc++;
}
else if ( islower(k) ) {
lc++;
}
}
// ...
您應該首先使用一種方法僅在一次while
循環中迭代一次字符串while
然后嘗試讀取不僅需要的內容,還應該讀取不應該計算的內容。 如果\\t
或\\n
會發生什么情況,您是否也需要計數?
這是一種可以幫助您理解的方法:
#include <stdio.h>
int main( void )
{
char string[] = "AbcDEfgHiJKlmnOPqrstUVWxyZ\n§$%$§";
int uc, lc, i, others;
uc = lc = i = others = 0;
while ( string[i] )
{
if ( string[i] >= 'A' && string[i] <= 'Z' )
{
uc++;
}else if ( string[i] >= 'a' && string[i] <= 'z' ){
lc++;
}else{
others++;
}
i++;
}
if ( i == ( lc + uc + others ) )
{
printf( "OK\n\n" );
printf("Uppercase Letters = %i \nLowercase Letters = %i \nOthers = %d \n", uc, lc, others );
printf("Total = %d\n", i );
}else
{
printf("Something went Wrong.\n\n");
}
}
您的if/else
語句可以很容易地被ctype.h
isupper( string[i] )
和islower( string[i] )
函數替換。
if ( isupper( string[i] ) )
{
uc++;
}else if ( islower( string[i] ) )
{
lc++;
}else{
others++;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.