多次运行该函数时的结果不同 - C.

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多次运行该函数时的结果不同 - C.相关的知识,希望对你有一定的参考价值。

我已经编写了一个函数,当我运行它一旦它完美运行时,但是当我用不同的输入运行它多次出错时。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define MAX_SIZE 20

int SumStr(char *str) {
  int i = 0, j = 0, num = 0, tempnum = 0;
  char temp[MAX_SIZE];
  while (*(str + i) != 0) { //While not NULL - Checked
    while (((*(str + i)) >= 48) && ((*(str + i)) <= 57)) { //while str[i] is [0-9]
        *(temp + j) = *(str + i);
        ++j; ++i;
    }
    if (j != 0) {
        tempnum = atoi(temp);
        num = tempnum + num;
        tempnum = 0;
        j = 0;
    }
    ++i;
}
return num;
}

void Test3(char *arr, int sum)
{

int tempSum = SumStr(arr);
if (tempSum != sum)
{
    printf("Your Output is %d, Expected: %d (-3)
", tempSum, sum);
}
}

void main() {

Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
}

该函数的目的是对字符串中的所有数字求和。

当我用这个主程序运行一次这个功能时(例如),它运行得很好;

void main() {
Test3("1$0!100", 101);
}

Output: num=101

但是当main使用不同的输入多次运行该函数时,输出完全错误。


这个主要的输出;

void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
}

是;

Your Output is 6871, Expected: 15
Your Output is 6718, Expected: 1234
Your Output is 5024, Expected: 101
答案

一个问题是,在将temp字符传递给''之前,不要使用atoi字符终止它。你可以写:

temp[j] = '';  // or: *(temp + j) = '';
if (j != 0) { ...

请注意,将未使用''正确终止的字符序列传递给期望(已终止)字符串的函数会产生未定义的行为;这可能是你观察到的。

其次,如果输入字符串的最后一个字符是数字,则增加i两次,从而错过输入的字符串终止字符。这再次导致未定义的行为。为了解决这个问题,你可以在增加i之前检查你是否在字符串的末尾:

    if (*(str + i) != 0) {
      ++i;
    }
另一答案

除了不终止temp[j]之外,你还可以通过在内循环和外循环中递增str来跳过i中的终止字符。当你跳过终止时,它开始处理下一个字符串[或取决于你的编译器/操作系统,任何旧的垃圾]。

顺便说一下,while (isdigit(str[i]))不仅比你的更具可读性,便携性和高效性,它还使评论变得不必要。

另一答案

我想祝贺Lior Gingihashvili使用问题中显示的测试代码。也就是说,IMO是一种很好的工作方式。

此代码不会尝试修复原始代码 - 这已经由accepted answer完成。此代码显示了一种完全不同的方法来解决问题。它使用一组不同的库函数 - strcspn()strtol() - 它避免了对源字符串的任何复制(因此它不会遇到null终止字符串的问题)。

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

static
int SumStr(const char *str)
{
    int sum = 0;
    str += strcspn(str, "0123456789");
    while (*str >= '0' && *str <= '9')
    {
        /*
        ** Since *str is a digit, the value will not be negative and
        ** strtol() won't fail unless the value is too big for a long.
        ** Since we can't include <limits.h> (or <assert.h>, or
        ** <errno.h>), I plan to ignore overflow.
        */
        char *eon;
        long val = strtol(str, &eon, 10);
        sum += (int)val;
        str = eon + strcspn(eon, "0123456789");
    }
    return sum;
}

static
void Test3(char *arr, int sum)
{
    int tempSum = SumStr(arr);
    const char *pass_fail = (tempSum == sum) ? "**PASS**" : "!!FAIL!!";
    printf("%s Output: %5d, Expected: %5d, Data (%s)
",
           pass_fail, tempSum, sum, arr);
}

int main(void)
{
    Test3("ax3b5mt11f", 19);
    Test3("5$5$5", 15);
    Test3("1234", 1234);
    Test3("1$0!100", 101);
    Test3("1$1!1", 3);
    Test3("x$.!-_+", 0);
    Test3("xxx1000y2345z3456=23412!", 30213);
    Test3("-0+0-0+0-", 0);
    return 0;
}

运行时,代码生成:

**PASS** Output:    19, Expected:    19, Data (ax3b5mt11f)
**PASS** Output:    15, Expected:    15, Data (5$5$5)
**PASS** Output:  1234, Expected:  1234, Data (1234)
**PASS** Output:   101, Expected:   101, Data (1$0!100)
**PASS** Output:     3, Expected:     3, Data (1$1!1)
**PASS** Output:     0, Expected:     0, Data (x$.!-_+)
**PASS** Output: 30213, Expected: 30213, Data (xxx1000y2345z3456=23412!)
**PASS** Output:     0, Expected:     0, Data (-0+0-0+0-)

(是的:当我在代码中出现错误时,我确实得到了!!FAIL!!行。)

另一答案

正确运行程序:

//Explanations in the commemnts

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define MAX_SIZE 20

int SumStr(char *str) {
  int i = 0, j = 0, num = 0, tempnum = 0;
  char temp[MAX_SIZE];

  while (*(str + i) != 0) {
  //While not NULL - Checked

    while (  (( *(str + i)) >= '0') && ((*(str + i)) <= '9')  ) // more readable 
        { //while str[i] is [0-9]
            *(temp + j) = *(str + i);
            ++j;
            ++i;
        }

        if (j != 0) {

            *(temp + j) = 0; // termination of the string needed for atoi

            tempnum = atoi(temp);
            num = tempnum + num;

            tempnum = 0;
            j = 0;
        }

        // new:
        if (*(str + i) != 0) { 
            ++i;
        }
        else break; // detection of the end of string
    }


    return num;
}

void Test3(const char *arr, int sum)
{

    int tempSum = SumStr(arr);
    if (tempSum != sum)
    {
        printf("Your Output is %d, Expected: %d (-3)
", tempSum, sum);
    }
}

void main() {

    Test3("ax3b5mt11f", 19);
    Test3("5$5$5", 15);
    Test3("1234", 1234);
    Test3("1$0!100", 101);
    Test3("1$1!1", 3);
    return 0;
}

以上是关于多次运行该函数时的结果不同 - C.的主要内容,如果未能解决你的问题,请参考以下文章

使用不同的变量异步多次运行某些代码

Access VBA 函数为不同的用户产生不同的结果

EasyClick 运行代码片段出Null

EasyClick 运行代码片段出Null

UDF - 自动运行时的结果与遍历时的结果不同

JavaScript函数