练习9.7 Kochan。奇异输出

练习9.7 Kochan。奇异输出,c,C,我正在努力学习C语言,使用Kochan在第四版C语言中的编程。问题9.7目标是将字符串插入到另一个数组中。我应该写一个函数来完成这个任务。我有两个问题 当我让算法在通过if语句时打印结果时,它会生成所需的输出,但是当我将其更改为%s时,我只得到部分输出。我的直觉是一个空字符被放置在我不想要的地方,但我根本看不到它 为了查看发生了什么,我添加了一个printf来跟踪字母及其占用的数组空间。我惊讶地发现,第一个字母不是0,而是空白的,下一个字母被指定为0。如能对此有所了解,将不胜感激 感兴趣的功能是

我正在努力学习C语言,使用Kochan在第四版C语言中的编程。问题9.7目标是将字符串插入到另一个数组中。我应该写一个函数来完成这个任务。我有两个问题

当我让算法在通过if语句时打印结果时,它会生成所需的输出,但是当我将其更改为%s时,我只得到部分输出。我的直觉是一个空字符被放置在我不想要的地方,但我根本看不到它

为了查看发生了什么,我添加了一个printf来跟踪字母及其占用的数组空间。我惊讶地发现,第一个字母不是0,而是空白的,下一个字母被指定为0。如能对此有所了解,将不胜感激

感兴趣的功能是“插入字符串”

#包括
#包括
char x[]={“那天打错了儿子”};
字符文本[]={“每”};
int countString(字符x[]
{
int计数器,z;
对于(计数器=0;x[计数器]!='\0';++计数器)
z=计数器+1;
返回z;
}
void insertString(char text[],char x[],int n)//源,要输入的文本,其中
{
整数计数,时钟,i=countString(text),q=countString(x);
int计数器=0;
chary[i+q];
对于(计数=0;x[count]!='\0';++count){
如果(计数否则,如果(计数器原始练习在此处:

您的函数没有执行此操作。您需要将字符串插入另一个字符串not,以创建一个新字符串,并将两者混合。当然,您可以这样做,然后将其复制到原始字符串中-但这是最不有效的存档方式(内存和时间)

使用正确的类型

size_t mystrlen(const char *str)
{
    const char *end = str;
    while(*end++);

    return end - str - 1;
}

char *strinsert(char *dest, size_t pos, const char *istr)
{
    char *temp = dest, *work;
    size_t ilen = mystrlen(istr);
    size_t nmove;

    while(*temp) temp++;
    nmove = temp - dest - pos + 1;
    work = temp;
    temp += ilen;

    while(nmove--) *temp-- = *work--;
    work = dest + pos;
    while(*istr) *work++ = *istr++;

    return dest;
} 


int main()
{
    char dest[128] = "0123456789012345678901234567890123456789";

    printf("%s", strinsert(dest, 7, "ABCD"));
}

  • 您的条件在
  • 中是错误的。它应该是
    x[计数-计数器]!='\0'

  • 在第二种情况下,像这样在字符串例程中使用
    printf
    就可以进行调试,但编写通用函数是一种糟糕的方法,因为这样就无法使用其输出进行进一步的编程操作。这也会使我们很难对函数的状态如何相互作用进行推理cts以不可预测的方式显示打印数据的状态

    我假设您还没有了解从函数返回字符串的先决条件是什么。您可以同时将函数逻辑内联到main或
    printf

    再加上这一点,
    void
    函数需要重新分配字符串中的空间,以插入到和中。这似乎不像分配一个新字符串来保存结果那样有用

    在不需要的情况下使用全局变量,如
    char x[]
    ,这是一种糟糕的做法。最好将这些字符串的作用域设置为
    main
    。由于您的函数除了可以访问其参数外,还可以访问这些变量,因此当作用域和封装被破坏时,可能会导致混淆

    使用一致的格式,避免变量名,如
    q
    ,它们实际上毫无意义。不要添加注释来解释糟糕的变量名:

    void insertString (char text[],char x[],int n) //source, text to input, where
    
    您可以简单地将变量准确地命名为它们所代表的名称:

    void insertString(char *dest, char *source, int add_index)
    
    另外,现在您已经掌握了
    countString
    ,您可以通过调用内置
    strlen
    来抽象它

    请确保在缓冲区中分配足够的空间:
    char y[i+q];
    应为
    y[i+q+1]
    ,以便为空终止符
    '\0'
    留出空间

    至于逻辑,我认为在没有条件的情况下分成三个循环比在有条件的情况下分成一个循环更容易。这使得将问题分成三个组成步骤更容易:

  • 将所有内容相加,直到
    Add_index
    dest
    字符串添加到结果
  • 字符串中的所有内容添加到结果中
  • Add_index
    后的所有内容从
    dest
    字符串添加到结果
  • 使用这种方法,剩下的就是找出如何适当地映射索引。下面是代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char *insert_string(char *dest, char *source, int add_index) {
        int source_len = strlen(source);
        int dest_len = strlen(dest);
        int result_size = source_len + dest_len + 1;
        char *result = malloc(result_size);
    
        for (int i = 0; i < add_index; i++) {
            result[i] = dest[i];
        }
    
        for (int i = 0; i < source_len; i++) {
            result[i+add_index] = source[i];
        }
    
        for (int i = add_index; i < dest_len; i++) {
            result[i+add_index] = dest[i];
        }
    
        result[result_size-1] = '\0';
        return result;
    }    
    
    int main(void) {
        char *result = insert_string("hello world", "cruel ", 6);
        printf("%s\n", result);
        free(result);
        return 0;
    }
    

    这样做更简单。因为结果已经有前缀,所以可以复制目的后缀,在中间创建一个源大小的间隙,然后使用源字符串覆盖该间隙。这取决于调用方,以确保目的缓冲区足够大以保持插入。

    #include <stdio.h>
    #include <string.h>
    
    void insert_string(char *dest, char *source, int add_index) {
        int source_len = strlen(source);
        int dest_len = strlen(dest);
    
        for (int i = add_index; i < dest_len; i++) {
            dest[i+add_index] = dest[i];
        }
    
        for (int i = 0; i < source_len; i++) {
            dest[i+add_index] = source[i];
        }
    }
    
    int main(void) {
        // allocate extra space in the string to hold the insertion
        char greeting[32] = "hello world";
        insert_string(greeting, "cruel ", 6);
        printf("%s\n", greeting);
        return 0;
    }
    
    #包括
    #包括
    void insert_字符串(char*dest、char*source、int add_索引){
    int source_len=strlen(source);
    int dest_len=strlen(dest);
    for(int i=add_index;i

    需要注意的是:这些函数都不能处理错误,因此它们是不安全的。正确的函数应该检查
    add_index
    是否在
    dest
    字符串的范围内。这是读者的练习。

    如果它所做的只是插入,那么这似乎是一个过于复杂的
    insertString
    函数在特定点将一段文本转换成另一个字符串。它是否应该执行类似于插入字符串(“示例”,“moo”,4)
    的操作,并为您提供
    “examoople”
    ?提示:在C语言中,尝试使用指针为您完成繁重的工作,而不是使用中间计数器。将指针用作计数器。
    for(char*p=x;*p;++p)#include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char *insert_string(char *dest, char *source, int add_index) {
        int result_size = strlen(dest) + strlen(source) + 1;
        char *result = malloc(result_size);
        char pre[add_index+1];
        pre[add_index] = '\0';
        strncpy(pre, dest, add_index);
        sprintf(result, "%s%s%s", pre, source, dest + add_index); 
        return result;
    }
    
    int main(void) {
        char *result = insert_string("hello world", "cruel ", 6);
        printf("%s\n", result);
        free(result);
        return 0;
    }
    
    #include <stdio.h>
    #include <string.h>
    
    void insert_string(char *dest, char *source, int add_index) {
        int source_len = strlen(source);
        int dest_len = strlen(dest);
    
        for (int i = add_index; i < dest_len; i++) {
            dest[i+add_index] = dest[i];
        }
    
        for (int i = 0; i < source_len; i++) {
            dest[i+add_index] = source[i];
        }
    }
    
    int main(void) {
        // allocate extra space in the string to hold the insertion
        char greeting[32] = "hello world";
        insert_string(greeting, "cruel ", 6);
        printf("%s\n", greeting);
        return 0;
    }