在 Mac 终端中编译后,C 程序未给出预期结果

C programs not giving expected results after compiling in Mac terminal

提问人:user22532748 提问时间:11/15/2023 最后编辑:Craig Esteyuser22532748 更新时间:11/15/2023 访问量:50

问:

我有一个项目,在MacBook终端中编译了24个C文件,每个文件都包含自己的功能。我使用 ar rcs libLibrary_name.a * .o 为这些函数创建了一个库,使用 gcc -c * .c 编译了它们,然后使用命令 gcc -o strtester strtester.c -L. Library_name.a 运行了我的驱动程序 strtester。虽然代码不会崩溃,但其中三个函数不会在驱动程序中提供预期的输出,尽管示例代码在这些文件中按预期运行。只有 24 个函数的这三个函数不起作用,我不确定为什么这些函数没有专门编译。

#include "string_library.h"
#include <stdio.h>
#include <ctype.h>
int
all_letters(char *s)
{
    if (is_empty(s) == 1) {
        return 0;
    }
    char *temp = s;
    int all_letters = 1;

//Loops through , returning 0 if we
//find a non-alphabetic character, or 1
//otherwise. Since words can have spaces between
//them, if the string is not empty we ignore
//spaces
    while (*temp != '\0') {
        if (isalpha(*temp) == 0 && (*temp) != ' ') {
            all_letters = 0;
            break;
        }
        ++temp;
    }
    return all_letters;
}

以上内容在文件中工作正常,但在编译时,它说“Hello World”和“Hell0 World”都不包含所有字母。虽然从技术上讲两者都有空格,但代码的编写方式是,如果发现字符串不为空,它将检查所有字母并忽略空格(因此只有数字和特殊字符应该返回失败,这在 strtester 中不会发生)

#include "string_library.h"
#include <stdio.h>
int
is_empty(char *s)
{
    // If the string is null, it's empty
    if (s == NULL) {
        return 1;
    }
    // Checks if there are any non-whitespace characters
    while (*s != '\0') {
        if (*s != ' ') {
            return 0;
        }
        s++;
    }
    return 1;
}

在实现它的文件中工作正常,但在驱动程序中给出相反的结果(说像“ ”这样的空字符串不为空,像“Hello”这样的字符串是空的)

#include "string_library.h"
#include <stdio.h>
#include <stdlib.h>
void
rm_empties(char **words)
{
    // Indexes to help us remove strings
    int total_index = 0;
    int current_index = 0;

    // Loops through until we reach the null pointer
    while (words[total_index] != NULL) {

        // Checks if the current string is not empty
        int empty = is_empty(words[total_index]);

        if (empty == 0) {
            // If it's not empty, we copy it into words
            words[current_index] = words[total_index];
            current_index++;
        }
        total_index++;
    }
    // Caps off the array with the null pointer
    words[current_index] = NULL;
}

int
main()
{
    puts("Test for rm_empties");
    char *to_empty[] = { "Hello", "World", " ", " ", "Steph", NULL };
    puts("Array before emptying:");
    int i = 0;

    while (to_empty[i] != NULL) {
        printf("%s\n", to_empty[i]);
        i++;
    }
    char **s = to_empty;

    rm_empties(to_empty);
    puts("Array after emptying:");
    int j = 0;

    while (s[j] != NULL) {
        printf("%s\n", s[j]);
        j++;
    }
}

在实现它的文件中工作正常,但在驱动程序中完全擦除数组。例如,给定数组 : {“Hello”, “Goodbye”, “ ”, “ ”, “Yes”, NULL},它只是擦除所有元素,而不是留下 “Hello”、“Goodbye” 和 “Yes” (null 指针停留以限制数组,因此保留是可以的)

以下是此 strtester 中每个函数的测试:

All_Letters:
puts("Test for all letters");
char *all_test = "Hello";
char *all_test_2 = "Hell0";
int is_all_letters = all_letters(all_test);

if (is_all_letters == 1) {
    printf("All characters in %s are letters\n\n", all_test);
}
else {
    printf("All characters in %s are not letters\n\n", all_test);
}

int is_all_letters_2 = all_letters(all_test_2);

if (is_all_letters_2 == 1) {
    printf("All characters in %s are letters\n\n", all_test_2);
}
else {
    printf("All characters in %s are not letters\n\n", all_test_2);
}

is_empty:
puts("Test for is_empty");
int is_empty_1 = is_empty(" ");

printf("%d", is_empty_1);
if (is_empty_1 == 0) {
    puts("The string " "is not empty");
}
else {
    puts("The string " " " " is  empty");
}

int is_empty_2 = is_empty("Hello");

if (is_empty_2 == 0) {
    puts("The string Hello is not empty");
}
else {
    puts("The string Hello is empty");
}

Rm_empties:
puts("Test for rm_empties");
char *to_empty[] = { "Hello", "World", " ", " ", "Steph", NULL };

puts("Array before emptying:");
int i = 0;

while (to_empty[i] != NULL) {
    printf("%s\n", to_empty[i]);
    i++;
}

char **s = to_empty;

rm_empties(to_empty);
puts("Array after emptying:");
int j = 0;

while (s[j] != NULL) {
    printf("%s\n", s[j]);
    j++;
}

感谢您的帮助!

c macOS 终端 器错误编译

评论

0赞 Retired Ninja 11/15/2023
请将您的代码直接编辑到问题中,作为最小的可重现示例。对于术语,您遇到的是运行时问题或错误,而不是编译问题。
1赞 paddy 11/15/2023
如果你能把你的代码放到谷歌文档中,那么你就可以把你的代码放到你的Stack Overflow问题中。您在此处的外部链接是一个隐私问题,因为任何使用 Google 帐户登录并访问这些链接的人都可以看到您。我现在实际上要删除你的链接,你可以适当地编辑你的问题。
0赞 Armali 11/15/2023
@user22532748 – 你真的使用 gcc -c * .c 编译了它们吗?
0赞 user22532748 11/16/2023
我确实用 gcc -c * .c 编译了它们,因为这是我的导师给我的,而且它工作正常(当然减去上述错误)。有没有更好的方法可以在终端中编译多个文件?有时,我们得到的终端命令并不总是在我的机器上起作用,所以如果有更好的方法,我真的很好奇。

答:

0赞 Harith 11/15/2023 #1

我不确定为什么这些没有专门编译。

他们已经成功编译。你所描述的不是编译错误,而是逻辑错误或错误。

我对您的代码进行了一些修改,用于代替手动检查,用断言替换了大多数调用,并且无法重现您描述的问题。我没有看到您的驱动程序代码有什么特别的问题,也没有看到函数本身有什么特别的问题,所以问题出在别处。isspace()printf()

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <stdbool.h>

static bool is_empty(const char *s) 
{
    if (!s) {
        return true;
    }

    while (*s) {
        if (!isspace(*(unsigned char *)s)) {
            return false;
        }
        ++s;
    }
    return true;
}

static void rm_empties(const char **words) 
{
    size_t total_index = 0;
    size_t current_index = 0;

    while (words[total_index]) {
        bool empty = is_empty(words[total_index]);

        if (!empty) {
            words[current_index] = words[total_index];
            ++current_index;
        }
        
        ++total_index;
    }
    words[current_index] = NULL;
}

static bool is_all_letters(const char *s)
{
    if (is_empty(s)) {
        return 0;
    }

    while (*s) {
        if(!isalpha(*(unsigned char *)s) && !isspace(*(unsigned char *)s)) {
            return false;
        }
        ++s;
    }
    return true;
}

int main(void)
{
    assert(is_empty(""));
    assert(!is_empty("a"));
    assert(!is_empty("Hello"));

    assert(is_all_letters("bigbang"));
    assert(!is_all_letters("49ckancas#($"));
    assert(!is_all_letters("       "));
    assert(!is_all_letters("Hell0"));

    const char *sample[] = {"Hello", "World", " ", "", "Steph", NULL};
    size_t i = 0;

    puts("BEFORE: "); 
    
    while(sample[i]) {
        puts(sample[i]);
        ++i;
    }

    rm_empties(sample);
    i = 0;
    
    puts("AFTER: ");

    while(sample[i]) {
        puts(sample[i]);
        ++i;
    }
    
    return EXIT_SUCCESS;
}

输出

$ ./str.exe
BEFORE:
Hello
World


Steph
AFTER:
Hello
World
Steph

评论

0赞 user22532748 11/16/2023
感谢您的回复!终端往往对小事非常挑剔,所以我会尝试这些,看看是否能解决我的问题。