使用strncpy的instream中的垃圾值

时间:2015-04-11 05:50:40

标签: c++ string char scanf strncpy

我正在运行以下程序。我在B.txt中获取前63个字符值,然后将A.txt中的浮点值附加到A.txt的第62列开始,位于B.txt行的末尾}

所以如果B.txt包含:

I am running the following program below. I am taking the firstXXXXXXXX

和A.txt包含:

I am running the following program below. I am taking the fir3.14

我希望B.txt看起来像:

I am running the following program below. I am taking the first3.14

然而,我得到的输出是:

I am running the following program below. I am taking the firstBUNCH OF JUNK3.14

int main()
{
    loadfileB("B.txt");

    return 0;
}


void loadfileB(char* fileName)
{
    FILE* fp = fopen(fileName, "r");
    char line[82];
    vector<int> rownum;
    vector<float> temp;
    temp = loadfileA("A.txt");

    int i = 0;
    ofstream fout("output.txt");

    while (fgets(line, 81, fp) != 0)
    {
        radius=temp[i];
        char buffer[64]; 
        strncpy(buffer, line, 63);
        fout << buffer<< " " << radius << endl;
        i++;
    }
    fclose(fp);
}

vector<float> loadfileA(char* fileName)
{
    FILE* fp = fopen(fileName, "r");
    char line[82];
    vector<int> rownum;
    vector <float> tempvec;

    int i = 0;
    while (fgets(line, 81, fp) != 0)
    {
        float temp;
        getFloat(line, &temp, 60, 6);
        tempvec.push_back(temp);
    }
    fclose(fp);

    return tempvec;
}

void getFloat(char* line, float* d, int pos, int len)
{
    char buffer[80];
    *d = -1;
    strncpy(buffer, &line[pos], len);
    buffer[len] = '\0';
    sscanf(buffer, "%f", d);
}

1 个答案:

答案 0 :(得分:2)

strncpy是一个糟糕的功能。这是因为如果输入不适合缓冲区,它不会对输出进行空值终止。您看到的垃圾是将非空终止缓冲区传递给期望以null结尾的字符串的函数的结果。

最简单的解决方法是替换:

char buffer[64]; 
strncpy(buffer, line, 63);

使用:

std::string buffer = line;
buffer.resize(63);

在您的其他用法中,您执行null-terminate,但是您永远不会检查len是否小于80。同样,更简单的解决方案是:

std::string buffer( line + pos, len );
sscanf(buffer.c_str(), "%f", d);

getFloat函数应该有一些信号错误的方法(返回值;如果sscanf没有返回1则抛出异常)。

当然,你也可以用C ++风格的代码替换很多其他C风格的代码,并完全避免缓冲区大小问题。