[英]How to replace specific numbers by another number in a text file (C++)
First, I want to mention that I'm completely new to C++, so it's possible that I've overlooked any obvious solutions.首先,我想提一下,我对 C++ 完全陌生,因此我可能忽略了任何明显的解决方案。
My task is to replace any non-zero number with 1.我的任务是用 1 替换任何非零数字。
The file looks like this:该文件如下所示:
Some text
0;0;0;0;0;0.236223;0;0;0;0;0;0.312757;0;0;0;0;0;0;0;0;0;0.367119;... (multiple lines)
and should turn into:并且应该变成:
Some text
0;0;0;0;0;1;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;1,... (multiple lines)
My idea was to start out with a string replacement code.我的想法是从字符串替换代码开始。 I tried the following:
我尝试了以下方法:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream filein( "input.txt" );
ofstream fileout( "output.txt" );
string toreplace = "0";
string replacewith = "1";
string text;
while ( getline( filein, text ) )
{
for ( size_t p = text.find( toreplace ); p != string::npos;
p = text.find( toreplace , p ) )
text.replace( p, toreplace.length(), replacewith );
fileout << text << endl;
}
return 0;
}
This gives back:这会返回:
1;1;1;1;1;1.236223;1;1;1;1;1;1.312757;1;1;1;1;1;1;1;1;1;1.367119,...
which is the opposite of what I want (not entirely).这与我想要的相反(不完全)。 So, I thought it would be easy to declare
toreplace
and replacewith
as floats and use != 0
, which didn't work, especially because I can't define text
as float because it contains ";".所以,我认为很容易将
toreplace
和replacewith
声明为浮点数并使用!= 0
,这不起作用,特别是因为我无法将text
定义为浮点数,因为它包含“;”。 (Do I need to remove this delimiter? I would still need it in the final text file.) (我需要删除这个分隔符吗?我仍然需要在最终的文本文件中使用它。)
The other problem in that code is that it replaces every zero, which includes "0.236223" turning into "1.236223".该代码中的另一个问题是它替换了每个零,其中包括“0.236223”变成“1.236223”。 I assume this wouldn't matter when eventually working with floats instead of strings.
我认为这在最终使用浮点数而不是字符串时无关紧要。
Is this the right approach to the given task, or would it be better to do it a different way?这是完成给定任务的正确方法,还是以不同的方式执行它会更好? Thanks for any help given.
感谢您提供的任何帮助。
EDIT: There was a ";"编辑:有一个“;” at the end of each line, which I didn't want and used the string::pop_back() function to resolve the problem.
在每一行的末尾,我不想要并使用 string::pop_back() 函数来解决问题。
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream filein("input.txt");
ofstream fileout("output.txt");
string toreplace = "0";
string replacewith = "1";
string text, new_text="";
while (getline(filein, text))
{
new_text = "";
double num;
while (sscanf_s(text.c_str(), "%lf;", &num))
{
if (num)
new_text += "1;";
else
new_text += "0;";
while (text.length() && text.at(0) != ';')
{
text.erase(0,1);
}
text.erase(0,1);
if (text.empty())
break;
}
fileout << new_text << endl;
}
return 0;
}
If you are able to simplify your input file the solution can be one-liner.如果您能够简化输入文件,则解决方案可以是单行的。
#include <iostream>
#include <iterator>
#include <algorithm>
#include <fstream>
int main()
{
std::ifstream filein("./data/input.txt"); // Contains 1. 2.3 0. 3.2
std::ofstream fileout("./data/output.txt"); // Should contain 1. 1. 0. 1.
std::replace_copy_if(std::istream_iterator<double>(filein), std::istream_iterator<double>(), std::ostream_iterator<double>(fileout," "),
[](auto v) {return v != 0.; }, 1.);
return EXIT_SUCCESS;
}
If you have to stick with the ';'如果你必须坚持使用';' delimiter it can be done with a two-liner:
分隔符它可以用两行来完成:
#include <iostream>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <fstream>
int main()
{
std::ifstream filein("./data/input.txt"); // Contains 1. 2.3 0. 3.2
std::ofstream fileout("./data/output.txt"); // Should contain 1. 1. 0. 1.
std::stringstream replaced;
std::replace_copy_if(
std::istream_iterator<char>(filein),
std::istream_iterator<char>(),
std::ostream_iterator<char>(replaced),
[](auto v) { return v == ';'; },
' ');
std::replace_copy_if(
std::istream_iterator<double>(replaced),
std::istream_iterator<double>(),
std::ostream_iterator<double>(fileout,";"),
[](auto v) {return v != 0.; },
1.);
return EXIT_SUCCESS;
}
And, just to be complete.而且,只是为了完成。 The solution with a regex.
用正则表达式解决。 The regex gives you the ability to specify more precisely what you want to search:
正则表达式使您能够更精确地指定要搜索的内容:
And the result is also an one-liner (one Statement)而且结果也是单行(one Statement)
Please see:请参见:
#include <iostream>
#include <sstream>
#include <regex>
#include <iterator>
const std::string testData{"0;0;0;0 ; 0;0.236223;0;0;0;0;0;0.312757;0;0;0;0;0;0;0;0;0;0.367119"};
// This is, what we would like to match. Any number, int or double
const std::regex re{"([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)"};
int main()
{
std::transform(
std::sregex_token_iterator(testData.begin(), testData.end(), re, 1),
std::sregex_token_iterator(),
std::ostream_iterator<int>(std::cout,";"),
[](const std::string& s) -> int { double d=stod(s); return d==0.0 ? 0 : 1; }
);
return 0;
}
If you do not want to have the trailing ';'如果你不想有尾随的 ';' then you can use.
那么你可以使用。
std::experimental::make_ostream_joiner(std::cout,";"),
instead of the std::ostream_iterator.而不是 std::ostream_iterator。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.