判斷整數/浮點數,並分別求乘積和比大小

Mars
各位前輩好
問題如下(請使用C語法)
請讓使用者依序輸入數字,直到輸入q停止。

列印出浮點數之乘積的和(所有浮點數相乘)。
列印出整數之乘積的和(所有整數相乘)。
比較上面兩者的大小,並列印出
"Float > Int"或"Float = Int"或"Float < Int"

小弟想到使用字串用'.'來判斷是否為小數
但剛學許多地方,懇請各位前輩指點
謝謝



#include<stdio.h>

int main(){
	char str[8];
	int i, strLen;
	int intnum=1;
	double doublenum=1;
	
	while(str!='q'){
		scanf("%s",&str);
		intnum = atoi(str);
		strLen = strlen(str);
		for(i=0;i<strLen;i++){
			if(str[i] == '.'){
				printf("%s\n",str[i]);
			}else{
				printf("%s\n",str[i]);
			}
		}
	}
	
	return 0;
}

最有價值解答

Raymond
你用
char str[8]; 

所以最多只能存 7 個字元長度的字串 (str[0...6]), 因為你至少要保留一個位子給終結字元。
建議用 #define 符號來取代 8.

while(str!='q'){ 

這裡有兩個錯誤, 首先 str != 'q' 是錯誤的語法。'str' 在運用時是個指標, 指向陣列第一個元素: str 等同於 &str[0], 所以指標是不能跟字元來做比較的。字串的比較要用 strcmp() 或 strncmp()。有些編譯器有支援 _stricmp() 及 _strnicmp(), 但它們不是標準函式.

另外一個嚴重的問題是: 在這裡, 'str' 並沒賦值, 也沒初始化, 它的內容可以是任何值, 直接拿來檢查內容會導致不可預期的結果。最簡單的作法就是在定義 str 陣列時順便初始化:
    char str[8] = { 0 };



scanf("%s",&str); 

這是不安全的寫法, 因為它無法阻止使用者輸入超過 str 陣列的長度, 而這一旦發生, 就會導致不可預期的結果。
你可以用:
scanf("%7s",&str); 

來告訴 scanf() 最多讀入 7 個字元. 但這種寫法不太方便, 因為如果你更改陣列長度, 你就得逐行檢查看哪裡需要更新。當然要自動化也不是不行, 用 C 語言的 preprocessing 就可以自動化:
#define MAX_STR_LEN 8
#define MAKE_STRING(x) #x
#define FORMAT_S(x) "%" MAKE_STRING(x) "s"

int main()
{
    char str[MAX_STR_LEN+1] = { 0 }; /* 取了個巧, 把長度 +1 */
    ...
    scanf(FORMAT_S(MAX_STR_LEN), str); /* ==> scanf("%" "8" "s", str)
                                          ==> scanf("%8s", str) */
}


要不然也可以考慮用 fgets(), 只是它會把輸入的 return 鍵 '\n' 也存入。 下面的例子會示範 fgets() 的用法。

intnum = atoi(str); 

atoi/f/l 其實並不好用, 因為它們無法提供錯誤訊息。比較好的函式是 strtol/ul/d, 因為它們可以提供更多訊息。

大概就這樣,下面是完整程式:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_STR_LEN 8

int main()
{
    char str[MAX_STR_LEN] = { 0 };
    long lproduct = 1;
    double dproduct = 1;

    while (1)
    {
        size_t slen = 0;
        fgets(str, MAX_STR_LEN, stdin);

        if (strncmp(str, "q", MAX_STR_LEN) == 0)
            break;

        long lValue;
        double dValue;
        char* pEnd;
        lValue = strtol(str, &pEnd, 0);
        if (*pEnd == 0 || *pEnd == '\n')
        {
            lproduct *= lValue;
            printf("%ld is integer.  product so far = %ld\n", lValue, lproduct);
        }
        else
        {
            dValue = strtod(str, &pEnd);
            if (*pEnd == 0 || *pEnd == '\n')
            {
                dproduct *= dValue;
                printf("%s is float.  product so far = %lf\n", str, dproduct);
            }
            else
            {
                printf("%s is not integer or float.\n", str);
            }

        }
    }

    printf("result...");
    if (dproduct > lproduct)
        printf("float > int\n");
    else if (dproduct < lproduct)
        printf("float < int\n");
    else
        printf("flaot = int\n");

    return 0;
}

Mars
感謝Raymond前輩解說
好多語法都不認識,小弟會再研究
經測試後發現q不會離開迴圈....
Raymond
>經測試後發現q不會離開迴圈...
if (strncmp(str, "q\n", MAX_STR_LEN) == 0) 

因為 fgets() 會存入 enter 鍵, 所以比較的話也要把 '\n' 考慮進去。要不然就要把 str 裡面的 \n 取掉:
    while (1)
    {
        size_t slen;
        fgets(str, MAX_STR_LEN, stdin);
        slen = strlen(str);
        if (str[slen - 1] == '\n')
            str[slen - 1] = 0;
         
        if (strncmp(str, "q", MAX_STR_LEN) == 0)
            break;
        ...
    }

Mars
感謝Raymond前輩解說
小弟再研究研究
回到頂部