【问题标题】:The basics of using strings and substrings in C programming [closed]在 C 编程中使用字符串和子字符串的基础知识 [关闭]
【发布时间】:2014-10-21 23:14:40
【问题描述】:

我一直在尝试通过阅读教科书来学习 C 编程,但对字符串和子字符串的工作方式感到困惑。 我知道什么是来自 java 的字符串和子字符串,但无法弄清楚 C 中的语法。

这是书中的一个问题,我认为可能很容易,但我无法理解。

编写并测试一个函数 Hydrox,如果它的字符串参数以子字符串 OH 结尾,则返回 1 为真。

建议使用 KOH 和 NaCl 测试功能。

另外,如何在字符串末尾删除和添加字母? 比如,如果出于某种原因我想将 NaCl 更改为 NaOH?

非常感谢任何帮助和解释。

预计到达时间: 我想我最困惑的是如何让程序查看字符串中的最后两个字母并将它们与 OH 进行比较。 我也不确定如何将字符串传递给函数。

【问题讨论】:

  • 这意味着如果你的字符串是"NaOH\n" 它将是真的。要查找子字符串 "OH" 是否在字符串中,您可以使用 char * strstr ( const char * str1, const char * str2 ) 函数。 例如strstr("NaOH", "OH");:如果返回 2(在这种情况下)则为 TRUE,但如果返回 NULL,则表示字符串中没有这样的子字符串。
  • @YulianKhlevnoy - 为什么这不是一个答案?

标签: c string substring


【解决方案1】:

String 是一个以特殊 null 结尾的字符 '\0' 结尾的字符序列。如果没有\0,则在找到\0 符号之前,使用字符串的函数不会停止。此字符可能出现在 pseudo 字符串(我的意思是没有\0 的字符串)结尾之后的任何位置,然后才停止。

下面的例子说明了这个空终止字符的必要性:

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

int main()
{
    char string[] = "Hello!";

    printf("original string:\n%s\n\n", string);

    memset(string, '-', 5);
    printf("memset doesn't affect the last two symbols: '!' and '\\0':\n%s", string);

    memset(string, '-', 6);
    printf("\n\nmemset doesn't affect the last symbol: '\\0':\n%s\n\n", string);

    memset(string, '-', 7);
    printf("memset affects all symbols including null-terminated one:\n%s", string);

    return 0;
}

/* OUTPUT:
original string:
Hello!

memset doesn't affect the last two characters: '!' and '\0':
-----!

memset doesn't affect the last character: '\0':
------

memset affects all characters including null-terminated one:
-------@↓@
*/

Substring 是字符串中的字符序列。它可能小于或等于字符串。 假设,"NaOH" 是一个字符串。那么子字符串可能是:"N""a""O""H""Na""aO""OH""NaO""aOH""NaOH"。要查找子字符串是否在字符串中,您可以使用strstr 函数。它的原型是char * strstr ( char * str1, const char * str2 );

这段代码显示了这个函数的结果:

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

int main()
{
    char *ptrCh = NULL;

    ptrCh = strstr("hello", "h");
    printf("ptrCh: %p\n", ptrCh);
    printf("%s\n\n", ptrCh);

    ptrCh = strstr("hello", "z");
    printf("ptrCh: %p\n", ptrCh);
    printf("%s\n\n", ptrCh);

    return 0;
}

/* OUTPUT:
ptrCh: 00403024
hello     

ptrCh: 00000000
(null)
*/

对于第一个printf,它从'h'的位置开始打印字符,当它到达'o'之后的下一个以null结尾的字符时,它就停止了,就像前面的程序一样。


为了使您的程序更具交互性,您可以声明数组,然后声明一个指向它的指针。数组大小必须足以存储最长的公式。假设,100 就足够了:

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

int main()
{
    char buf[100] = {0};
    char *ptr = &buf[0];

    scanf("%s", ptr);

    // printf() gets a pointer as argument
    printf("%s\n", ptr);   

    // printf() gets also a pointer as argument. 
    // When you pass arrays name without index to a function,
    // you pass a pointer to array's first element.
    printf("%s", buf);     

    return 0;
}

至于重写个字母在字符串的末尾。这是一个小程序。关注cmets:

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

int main()
{
    char buf[100] = {0};
    char formula[100] = {0};
    char compound[100] = {0};
    char *ptr = &buf[0];
    char *pFormula = &formula[0];
    char *pCompound = &compound[0];

    printf("Enter formula: ");
    scanf("%s", pFormula);
    printf("Enter chemical compound: ");
    scanf("%s", pCompound);

    // Copying the first chemical elements without the last
    // several that will be replaced by another elements.
    strncpy(ptr, pFormula, strlen(pFormula) - strlen(pCompound));
    // Adding new compound to the first elements.
    // Function also adds a null-terminated character to the end.
    strncat(ptr, pCompound, strlen(pCompound));

    printf("The new chemical compound is: ");
    printf("%s", ptr);

    return 0;
}

/* OUTPUT:
Enter formula: NaOH
Enter chemical compound: Cl
The new chemical compound is: NaCl
*/

【讨论】:

  • 哇,太棒了!感谢您花时间处理所有这些!我确实对重写字母的代码有疑问。对于strncpy(ptr, pFormula, strlen(pFormula) - strlen(pCompound));strlen(pFormula) - strlen(pCompound) 是什么意思?
  • @PeachesTasteGood,很高兴看到这对您有用。它是您要更改的最后一个字符之前的所有字符的数量。对于"CH3CH2OH"strlen(pFormula) - strlen(pCompound) 是 6 (CH3CH2),您将复制它们,但不包含最后 2 个字符 (OH)。然后你连接你的新化合物,比如(MgCl)。结果你会得到(CH3CH2MgCl)。附言抱歉,结果公式不正确 - 坦率地说,我不喜欢化学,但我知道它是物理科学的一个非常重要的分支。
【解决方案2】:

在 C 中,我们使用以 null 结尾的字符串。那就是“隐形”,0值。不是 ASCII “0”,而是零值,如 8 位 0x00。您可以用 '\0' 或 "\0" 或不带引号的 0 在文字文本中表示它,但是,在文字字符串中它是多余的,因为大多数函数,如 strcmp() 或 strstr() 或 strcat() 都期望并使用以空结尾的字符串。 Null char 是 C 标准字符串函数的停止符号。

使用 C 库调用实现这一点的一种简单方法是测试子字符串是否存在,然后测试该子字符串的长度,从而验证它是否位于字符串末尾。

假设 buf 是一些大的字符串缓冲区,char buf[1024]char *temp 是一个临时变量。

  1. temp = strstr(buf, "OH") 返回指向“OH”的指针,如果存在于 buf 中的任何偏移量。
  2. strlen(temp) 获取 temp 的长度,如果在字符串的末尾,它将是 2(不包括空终止符),所以如果原始字符串是 "OHIO" 或 "SOHO" 它不会匹配,因为它将是 4 并且3个。

以上是代码的核心,而不是完整的健壮实现。您需要检查有效的返回值等。

char buf[1024];
char *temp;

strcpy(buf, "NaOH");

if((temp = strstr(buf, "OH")) != 0)
{
      // At this point we know temp points to something that starts with "OH"
      // Now see if it is at the end of the string
      if(strlen(temp) == 2)
            return true;          // For C99 include stdbool.h

      return false;
}

您可能会变得晦涩难懂,并直接检查空终止符,这会更快一些。只要这段代码在 strstr() 的 if() 中,它就是安全的,否则如果你不知道一个字符串至少有 N 个字符长,就不要这样做。

      if(temp[2] == '\0')
            return true;          // For C99 include stdbool.h

至于附加到字符串,请阅读strcat 上的文档。请记住 strcat,您要追加到的缓冲区中必须已经有足够的空间。它不像 C++ std::string 或 Java/C# 字符串,它们会根据需要动态调整大小。在 C 中,您可以自己完成所有这些工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-16
    • 2020-10-19
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    相关资源
    最近更新 更多