字符对齐奇怪的输出

时间:2015-03-02 06:53:21

标签: c

我的代码位于底部。我试图取两个字符串并根据我收到的编辑记录来更改它们。我写了我的代码,但我不明白为什么我会得到如此奇怪的输出。我的目标是首先存储两个字符串的值,然后将它们变成一个2D数组,但是我在这个目标的第一部分失败了。这就是问题所在:

创建符合以下条件的函数:

输入:编辑记录和2个原始字符串(3个字符串)

输出:包含编辑后两个对齐的2 d数组

示例:

s1 = “vintner”
s2 = “writers”
trans = “RIMDMDMMI”

R代表"替换" 我代表"插入" M代表"匹配" D代表"删除" 回答:

alignment={“v_intner_”,
“wri_t_ers”}; //return a 2d array

功能原型:

char** getAlignment(char* s1, char* s2, char* s3);

以下是我的代码:

char TestS1[] = "vintner";
char TestS2[] = "writers";
char TestS3[] = "RIMDMDMMI";
char twoDarray[2][10];

char** getAlignment(char* s1, char* s2, char* s3){
    char transTemp[n];
    char s1Temp[n];
    char s2Temp[n];
    char sOne[n];
    char sTwo[n];
    strcpy(sOne, s1);
    strcpy(sTwo, s2);
    int jj;
    strcpy(transTemp, s3);
    int kk;
    for(jj=0, kk=0; jj<n, kk<n; jj++, kk++){

        if(transTemp[jj]=='R')
        {
            s1Temp[kk] = sOne[jj];
            s2Temp[kk] = sTwo[jj];
        }

        if(transTemp[jj]=='I'){
            s1Temp[kk] = '_';
            s1Temp[kk+1] = sOne[jj];
            s2Temp[kk] = sTwo[jj];
            kk++;
        }

        if(transTemp[jj] == 'M'){
            s1Temp[kk] = sOne[jj];
            s2Temp[kk] = sTwo[jj];
        }

        if(transTemp[jj] == 'D'){
            s2Temp[kk] = '_';
            s2Temp[kk+1] = sTwo[jj];
            s1Temp[kk] = sOne[jj];
            kk++;
        }


    }

    printf("\ns1Temp = %s\n", s1Temp);
    printf("\ns2Temp = %s\n", s2Temp);


    return 0;
}

main()
{
printf("The new method returns: ", getAlignment(TestS1,TestS2,TestS3));
return 0;
}

1 个答案:

答案 0 :(得分:1)

您的问题实际上有两个部分:如何返回两个字符串?为什么我没有得到所需的输出?

C中的字符串是字符数组。你很少返回字符串。将字符数组与其最大长度一起传递给函数更常见,并填充该数组。 <string.h>中的函数可以做到这一点。在我看来,一个好的设计模型是snprintf:它填充缓冲区,注意不要溢出它,确保结果正确地以null结尾并返回缓冲区足够大时写入的字符数。最后一个属性允许您传递一个null的长度(以及NULL指针的特殊情况),以找出您需要多少个字符并根据需要分配内存。

因此,您的函数原型可能如下所示:

int getAlignment(char *res1, char *res2, size_t n,
    const char* s1, const char* s2, const char* trans);

除非结果字符串在您的情况下长度不同。

你也可以返回字符串,但你要么必须在堆上返回用malloc分配的新内存,这意味着客户端代码必须显式地free,或者指向已经存在的内存。当然,您只能返回一个字符串。

您可以将函数中的多个值作为结构返回。在将函数传递给函数或从函数返回时,结构不会衰减为指针。我将在下面的示例中使用该方法。

至于第二个问题:你的主要问题是你有三个字符串 - 两个源字符串和一个翻译字符串 - 但只保留两个索引。所有字符串都是独立遍历的;字符串的索引之间没有同步。

您可以随时附加到结果字符串。 “driving”字符串是trenslation字符串,因此您应该只遍历主循环。

另外需要注意的是,您不需要复制源字符串。这不仅是必要的,而且也很危险,因为strcpy可能会溢出缓冲区。使用strncpy处理溢出会触发输入字符串。

我已更新您的实施:

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

#define N 10

struct Result {
    char res1[N];
    char res2[N];
};

struct Result getAlignment(const char* s1, const char* s2, const char* trans)
{
    struct Result res;

    int j1 = 0;             // index into s1
    int j2 = 0;             // index into s2
    int n = N - 1;          // leave 1 char for null terminator

    while (*trans) {

        if (*trans == 'R') {
            if (j1 < n) res.res1[j1++] = *s1++;
            if (j2 < n) res.res2[j2++] = *s2++;
        }

        if (*trans == 'I'){
            if (j1 < n) res.res1[j1++] = '_';
            if (j1 < n) res.res1[j1++] = *s1++;
            if (j2 < n) res.res2[j2++] = *s2++;
        }

        if (*trans == 'M') {
            if (j1 < n) res.res1[j1++] = *s1++;
            if (j2 < n) res.res2[j2++] = *s2++;
        }

        if (*trans == 'D') {
            if (j1 < n) res.res1[j1++] = *s1++;
            if (j2 < n) res.res2[j2++] = '_';
            if (j2 < n) res.res2[j2++] = *s2++;
        }

        trans++;
    }

    // null-terminate strings
    res.res1[j1] = '\0';
    res.res2[j2] = '\0';

    return res;
}

int main()
{
    char *str1 = "vintner";
    char *str2 = "writers";
    char *trans = "RIMDMDMMI";

    struct Result res = getAlignment(str1, str2, trans);

    printf("%s\n%s\n\n", res.res1, res.res2);

    return 0;
}

注意事项:

  • 通过指针遍历转换字符串,这会保存索引。

  • 仅当有足够的空间时才会附加结果字符串。您可以将N更改为5,并查看在4个字符后截断结果字符串的方式,从而丢失信息,但防止缓冲区溢出。

  • 结果字符串索引和源字符串指针都会随着时间的推移而增加。

  • 仅读取源字符串。 (这就是为什么复制没有意义。)因此,它们应该是函数签名中的const char *