简体   繁体   English

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

[英]Different results when running the function multiple times - C

I've written a function and when I'm running it once it works perfectly, but when I'm running it multiple times with different inputs something goes wrong. 我已经编写了一个函数,当我运行它一旦它完美运行时,但是当我用不同的输入运行它多次出错时。

#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)\n", 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);
}

The purpose of the function, is to sum all the numbers within the string. 该函数的目的是对字符串中的所有数字求和。

When I'm running the function once with this main (for example), it works perfectly; 当我用这个主程序运行一次这个功能时(例如),它运行得很好;

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

Output: num=101

But when the main runs the function multiple times with different inputs, the output is completely wrong. 但是当main使用不同的输入多次运行该函数时,输出完全错误。


The output from this main; 这个主要的输出;

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

Is; 是;

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

One issue is that you do not terminate your temp -string with a '\\0' -character before passing it to atoi . 一个问题是,在将其传递给atoi之前,不要使用'\\0'字符终止temp -string。 You could write: 你可以写:

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

Note that passing character sequence that is not correctly terminated with '\\0' to a function that expects a (terminated) string yields undefined behaviour; 请注意,将未使用'\\0'正确终止的字符序列传递给期望(终止)字符串的函数会产生未定义的行为; that's probably what you observe then. 这可能是你观察到的。

Second, if the last character of your input string is a digit, you increment i twice and thereby miss the string terminating character of the input. 其次,如果输入字符串的最后一个字符是数字,则增加i两次,从而错过输入的字符串终止字符。 This again leads to undefined behaviour. 这再次导致未定义的行为。 To overcome this, you could check if you are at the end of the string before incrementing i : 为了解决这个问题,你可以在增加i之前检查你是否在字符串的末尾:

    if (*(str + i) != 0) {
      ++i;
    }

In addition to not terminating temp[j] , you also skip the terminating character in str by incrementing i both in the inner loop and outer loop. 除了不终止temp[j] ,还可以通过在内循环和外循环中递增i跳过str的终止字符。 When you skip the termination, it starts processing the next string [ or depending upon your compiler/OS, any old crap ]. 当你跳过终止时,它开始处理下一个字符串[或取决于你的编译器/操作系统,任何旧的垃圾]。

btw, while (isdigit(str[i])) is not only more readable, portable and efficient than yours, it also makes the comment unnecessary. 顺便说一下, while (isdigit(str[i]))不仅比你的更具可读性,便携性和高效性,它也不需要注释。

I'd like to congratulate Lior Gingihashvili on using the test code shown in the question. 我要祝贺Lior Gingihashvili使用问题中显示的测试代码。 That is, IMO, an excellent way of working. 也就是说,IMO是一种很好的工作方式。

This code doesn't attempt to fix the original code — that's already been done by the accepted answer . 此代码不会尝试修复原始代码 - 这已经由接受的答案完成 This code shows a whole different way of approaching the problem. 此代码显示了一种完全不同的方法来解决问题。 It uses a different set of library functions — strcspn() and strtol() — and it avoids any copying of the source string (so it doesn't run into problems with null terminating strings). 它使用一组不同的库函数 - 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)\n",
           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;
}

When run, the code produces: 运行时,代码生成:

**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-)

(Yes: I did get !!FAIL!! lines when I had a bug in the code.) (是的:当我在代码中出现错误时,我确实得到了!!FAIL!!行。)

Correctly running program: 正确运行程序:

//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)\n", 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 多次运行 C 程序,每次使用不同的输入 - Running a C program multiple times with different inputs each time 为什么 valgrind 仅通过多次运行程序就报告不同的结果(没有泄漏可能/仍然可以到达)? - Why does valgrind report different results (no leaks are possible / still reachable) just by running the program multiple times? scanf 没有在循环中多次运行 C - scanf not running multiple times in loops C 等效的C函数,结果不同 - equivalent C function, different results 在Docker容器中运行时的结果不同 - Different results when running inside a docker container 从 Python 子进程与 Bash 运行 C 程序时的不同结果 - Different results when running C program from Python Subprocess vs in Bash 在不同时间运行流程会使事件无法正常工作-C - Running processes at different times stops events from working - C 将相同的代码放入函数中与将其内联 C 编写时的不同结果 - Different results when I put identical code in a function vs writing it inline C 如何防止fgets在缓冲区溢出时多次运行? - How to prevent fgets running multiple times when overflowing a buffer? 即使向量不同,也多次使用相同的 function - Using the same function multiple times even though the vectors are different
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM