【问题标题】:Beginner C programmer having problems with string functions初学者 C 程序员遇到字符串函数问题
【发布时间】:2013-12-27 03:35:56
【问题描述】:

我是一名 C 菜鸟,要回学校攻读 CS 硕士学位,所以我需要一些时间来提高我的技能。我想看看是否有人可以为我在编译以下代码时遇到问题提供一些帮助。我一直在关注 WiBit.net 上的视频并在 64 位 Linux 环境(Ubuntu 13.10)上进行开发。我正在使用 gedit 而 gcc 编译器没有 IDE。

这段代码在我的 Win 7 VM 上运行没有错误,但是当我尝试在我的主机 Linux 环境中执行它时,我遇到了错误:

源码:本例调用strcmp和strcmpi函数

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

int main()
{
    char str1[255];
    char str2[255];
    printf("str1: "); gets(str1);
    printf("str2: "); gets(str2);

    if(strcmp(str1, str2) == 0)
        printf("Strings match exactly!");
    else if(strcmpi(str1, str2) == 0)
        printf("Strings match when ignoring case!");    
    return 0;
}

错误消息(仅限 Linux):

$gcc main.c -o demo -lm -pthread -lgmp -lreadline 2>&1 /tmp/ccwqdQMN.o:在函数main': main.c:(.text+0x25): warning: thegets 中,函数很危险,不应使用。 main.c:(.text+0x8f): undefined reference to `strcmpi' collect2:错误:ld 返回 1 个退出状态

源代码 2:本示例使用 strupr 和 strlwr 函数

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

int main()
{
    char str1[255];
    char str2[255];
    printf("str1: "); gets(str1);
    printf("str2: "); gets(str2);

    strlwr(str1);
    strupr(str2);
    puts (str1);
    puts (str2);
    return 0;
}

错误消息(仅限 Linux):

$gcc main.c -o demo -lm -pthread -lgmp -lreadline 2>&1 /tmp/ccWnIfnz.o:在函数main': main.c:(.text+0x25): warning: thegets 中,函数很危险,不应使用。 main.c:(.text+0x57): 未定义对strlwr' main.c:(.text+0x6b): undefined reference tostrupr' 的引用 collect2:错误:ld 返回 1 个退出状态

如果有人愿意帮助而不是将我拆散,我希望得到详细的解释哈哈。我知道,对于最佳实践,由于缓冲区溢出(例如用户输入 750 个字符的字符串),我们不应该使用 get。最佳实践将使用 fgets 代替,但我的问题是我是否收到这些错误,因为这些函数不是 ANSI C 或什么的一部分。它们确实出现在我机器上的 man 文件中,这让我陷入了一个循环。

提前致谢!


更新: 你们真棒。接受了您的所有建议和 cmets,并且能够修改并制作用于字符串比较以及转换为上/下的示例程序。很高兴我能够让它在两个操作系统上都无错误地运行。

示例代码:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
    char str[255];
    printf("Enter a string: "); fgets(str,255, stdin);
    printf("Here is your original string, my master: %s\n", str);
    //Now let's loop through and convert this to all lowercase
    int i;
    for(i = 0; str[i]; i++)
    {
        str[i] = tolower(str[i]);
    }
    printf("Here is a lowercase version of your string, my master: %s\n", str);    
    //Now we'll loop through and convert the string to uppercase
    int j;
    for(j = 0; str[j]; j++)
    {
        str[j] = toupper(str[j]);
    }
    printf("Here is a uppercase version of your string, my master: %s\n", str);    
    return 0;
}

【问题讨论】:

  • 您应该查看cplusplus.com/reference/cstring 以获取对标准 C 字符串库的参考。
  • 如果你使用 gcc,你真的应该使用-Wall 来获得关于有问题的警告。
  • 谢谢克里斯。为此,我正在研究更多的命令行开关。我接触 C++ 已经有 5 年了,现在我要在回到学校之前及时回到古老的 C 语言。

标签: c linux string gcc


【解决方案1】:

strcmpi 问题:strcasecmp() 是 posix 标准,在 linux 中也是如此。

strupr 和 strlwr 在 glibc 中不存在,尽管您可以使用一行代码来实现它们,如下所示: c - convert a mixed-case string to all lower case

在编译中,首先你可以找到一个警告,因为 gcc 没有在包含的头文件中找到函数。在这种情况下,它认为它们被声明为 int funcname(void)。但后来,在链接时,它找不到这个不存在的函数的导出符号,因此它无法创建可执行文件。第二个错误是停止编译的原因。

c api的区别太多了,虽然posix标准处理了,但microsoft不照做。

【讨论】:

  • 感谢您的快速跟进!我在一些提到编写我自己的函数的帖子中做了一些。试图弄清楚为什么它可以在 Windows 上运行(我使用 MinGW - 最低安装)而不是我的 linux 机器,我有点沮丧。感谢您的回复。
  • MingW 使用自己的 c 库,而不是 glibc 端口。他们试图简化现有 msvc 代码的移植。 Glibc 人是一种更硬核的遵循标准的风格。但这些都是简单的单行函数(假设您不会转换非英语字符集,尽管也有很好的库调用)。
【解决方案2】:

正如您所指出的,gets 函数是不安全的,因为它不执行任何边界检查:您使用 255 个字符的字符串缓冲区调用它,但如果另一个程序写入的行长于 255字符,它可能会将数据写入您进程的堆栈,从而导致您的进程执行恶意代码(或至少产生分段错误)。

使用 fgets 代替:

printf("str1: "); fgets(str1, 255, stdin);
printf("str2: "); fgets(str2, 255, stdin);

如果您仔细阅读编译器的错误输出,您会注意到它不是在您使用 gets 时发出错误,而是发出警告。如果您修复 strcmpi 调用,您的代码仍应编译和执行。

【讨论】:

  • 也谢谢你。今晚我将尝试运行几个示例。在我完全理解这一点之前,我不想继续讨论任何其他概念。尽量不出错哈哈。
  • 请注意,虽然 gets() 函数已被弃用,因为它本身就已损坏,但 fgets() 函数的行为确实略有不同:它不会丢弃换行符 ('\n')。
猜你喜欢
  • 2023-02-04
  • 2020-07-26
  • 1970-01-01
  • 1970-01-01
  • 2021-05-13
  • 2014-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多