我决定在明年参加正式课程之前开始学习C ++,我已经开始了CodeEval和Project Euler的一些简单挑战。在这一个中,你必须获取一个包含单词串的输入文件,你必须输出文件的行,并带有反转的单词。这样一个文件具有以下输入
1:这是第一行
2:这是第二行
最终会成为
1:一行是这个
2:两行是这个
我编写了以下程序来做到这一点,除了没有正确地反转字符串,而是完全反转字,它尽管编译没有错误或警告,但分段错误。我假设我错过了一些关于C ++中正确内存管理的内容,但我不确定它是什么。那么有人可以告诉我关于内存管理的错误吗?
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
int main(int argc, char** argv)
{
std::string filename = argv[1]; //has to be argv[1], argv[0] is program name
std::string output_string; //final output
std::string line; //Current line of file
std::ifstream read(filename.c_str());
if(read.is_open()){
while(std::getline(read,line)){
std::string temp;
std::istringstream iss;
iss.str(line);
while(iss >> temp){ //iterates over every word
output_string.insert(0,temp); //insert at the start to reverse
output_string.insert(0," "); //insert spaces between new words
}
output_string.erase(0,1); //Removes the space at the beginning
output_string.insert(0,"\n"); //Next line
}
output_string.erase(0,1); //Remove final unnecessary \n character
read.close();
}
else{
std::cout<<"Unable to open file\n";
}
for(unsigned int i = output_string.length(); i>=0;i--){
std::cout<<output_string[i];
}
std::cout<<"\n";
}
答案 0 :(得分:1)
将最后一个for语句更改为
std::cout << output_string;
通过在输出字符串中的后打印字符来开始输出。这摆脱了段错误。现在你试图反向打印反向输出。
现在你发现你应该反转每一行,而不是整个文本。您可以通过在插入中为每一行添加起始索引而不是 0 来轻松完成此操作。
所以而不是
output_string.insert(0,temp); //insert at the start to reverse
你可以做到
output_string.insert(start_of_line, temp); //insert at the start to reverse
答案 1 :(得分:1)
for(unsigned int i = output_string.length(); i>=0;i--){
std::cout<<output_string[i];
}
这里发生了段错误;您可以通过一些额外的标志从编译器获得警告。例如g ++不会使用-Wall
生成警告,但会产生两个-Wextra
警告:一个关于argc
没有被使用,另一个关于此循环永远不会终止。
这里的问题有两个方面:正如长颈鹿队长所说,你开始超越实际的长度;但条件i >= 0
将始终为真,因为i
是无符号的。因此,一旦它达到0,下一个减量将导致它回绕到最高可能值,然后你肯定获得越界内存访问。
报告的警告是:
reverse.cpp:31:49: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
for(unsigned int i = output_string.length(); i>=0;i--){
同样长颈鹿队长说,你正在翻转整个文件,而不仅仅是每一行。因此,您可以反转每一行并在完成该行后输出它,而不是将整个输出存储起来以供日后使用。
这里的整个程序只需要很少的更改,以避免任何警告并获得正确的输出。主要的变化是将output_string
的所有用法转移到读取循环中。
int main(int argc, char** argv)
{
if (argc != 2)
{
std::cerr << "Need a file to process!" << std::endl;
return 1;
}
std::string filename = argv[1]; //has to be argv[1], argv[0] is program name
std::string line; //Current line of file
std::ifstream read(filename.c_str());
if(read.is_open()){
while(std::getline(read,line)){
std::string output_string; //final output
std::string temp;
std::istringstream iss;
iss.str(line);
while(iss >> temp){ //iterates over every word
output_string.insert(0,temp); //insert at the start to reverse
output_string.insert(0," "); //insert spaces between new words
}
output_string.erase(0,1); //Removes the space at the beginning
std::cout << output_string << std::endl;
}
read.close();
}
else{
std::cout<<"Unable to open file\n";
}
}