This is a part of my code. I don't know why the string was partially overwrite by another string.
for(int xd = 0 ; xd < 10; xd++)
{
if(booklist[xd].length() != 0)
{
string d = string(booklist[xd]);
string e = "1,2,3,4";
string f = d + e;
cout << d.length() << endl;
cout << d << endl;
cout << f.length() << endl;
cout << f << endl;
}
}
The result of this code is:
16
brave new world
23
1,2,3,4ew world
28
nineteen eighty-four (1984)
35
1,2,3,4n eighty-four (1984)
I don't know why i got this wrong result.
Could someone help me?
Are you populating booklist by pulling from a file that you copied from Windows to a linux machine?
Windows will add a carriage return '\r' to the end of each line in addition to a newline. If you're reading from a windows file and using getline, it'll pull the carriage return into the string.
When a carriage return is output in the terminal, it resets the cursor to the beginning of the line, which would result in the behavior you're seeing.
To fix this, see this question on trimming whitespace from a string. The function you're looking for from that answer is rtrim (or "right trim"):
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
It's likely that your booklist entries have trailing carriage returns, causing line 4 (for instance) to print brave new world, return to column 1, and print 1,2,3,4 over it. (That's why the character count is greater on line 3 than line 1, despite the two lines having the same apparent length.)
Strip the trailing whitespace from booklist entries (or figure out why it's getting in there in the first place, and deal with that) and things should be fine.
Yes i got the reason why it shows wrong.
Just like what scohe001 said: when i use getline to put the file in to an array, it will add \r after each element, so i use substr to remove the \r .Now it get work. Thanks every one.
Related
i have this project due however i am unsure of how to parse the data by the word, part of speech and its definition... I know that i should make use of the tab spacing to read it but i have no idea how to implement it. here is an example of the file
Recollection n. The power of recalling ideas to the mind, or the period within which things can be recollected; remembrance; memory; as, an event within my recollection.
Nip n. A pinch with the nails or teeth.
Wodegeld n. A geld, or payment, for wood.
Xiphoid a. Of or pertaining to the xiphoid process; xiphoidian.
NB: Each word and part of speech and definition is one line in a text file.
If you can be sure that the definition will always follow the first period on a line, you could use an implementation like this. But it will break if there are ever more than 2 periods on a single line.
string str = "";
vector<pair<string,string>> v; // <word,definition>
while(getline(fileStream, str, '.')) { // grab line, deliminated '.'
str[str.length() - 1] = ""; // get rid of n, v, etc. from word
v.push_back(make_pair<string,string>(str,"")); // push the word
getline(fileStream, str, '.'); // grab the next part of the line
v.back()->second = str; // push definition into last added element
}
for(auto x : v) { // check your results
cout << "word -> " << x->first << endl;
cout << "definition -> " << x->second << endl << endl;
}
The better solution would be to learn Regular Expressions. It's a complicated topic but absolutely necessary if you want to learn how to parse text efficiently and properly:
http://www.cplusplus.com/reference/regex/
Wanting to do some fancy formatting. I have several lines that I want to interact with each other. Get the first two lines. Print out the character in the second line times the integer in the first line. Seperate them all with a asterisk character. No asterisk after the final character is printed. Move onto the next integer and character. Print them on a separate line. Do this for the whole list. The problem I am having is printing them on separate lines. Example:
5
!
2
?
3
#
Desired output:
!*!*!*!*!
?*?
#*#*#
My output:
!*!*!*!*!*?*?*#*#*#*
Below is my code. Another thing to mention is that I am reading the data about the characters and numbers from a separate text file. So I am using the getline function.
Here is a chunk of the code:
ifstream File
File.open("NumbersAndCharacters.txt")
string Number;
string Character;
while(!File.eof(){
getline(File, Number);
getline(File, Character);
//a few lines of stringstream action
for (int i=0; i<=Number; i++){
cout<<Character<<"*";}//end for. I think this is where
//the problem is.
}//end while
File.close();
return 0;
Where is the error? Is it the loop? Or do I not understand getline?
It should be printing an "endl" or "\n" after each multiplication of the character is done.
Thanks to everyone for the responses!
You have not shown your code yet, but what seems to be the issue here is that you simply forgot to add a new line every time you print your characters. For example, you probably have done:
std::cout << "!";
Well, in this context you forgot to add the new line ('\n'), so you have two options here: first insert the new line yourself:
std::cout << "! \n";
Or std::endl;
std::cout << "!" << std::endl;
For comparison of the two, see here and here. Without further description, or more importantly your code that doesn't seem to work properly, we can't make suggestions or solve your problem.
I am trying to concatenate some string but it works in one but not another.
Working: I take in 2 argument and then do this. a = hello, b = world
string concat = a + b;
The output would be hello world with no problem.
Not working: I read from file and concatenate with 2nd argument. assuming string from file is abcdefg.
string concat = (string from file) + b;
and it gives me worldfg.
Instead of concatenating, string from b overwrites the initial string.
I have tried a few other methods such as using stringstream but it doesn't work as well.
This is my code.
int main (int nArgs, char *zArgs[]) {
string a = string (zArgs [1]);
string b = string (zArgs [2]);
string code;
cout << "Enter code: ";
cin >> code;
string concat = code + b;
}
// The output above gives me the correct concatenation.
// If I run in command prompt, and do this. ./main hello world
// then enters **good** after the prompt for code.
// The output would be **goodworld**
However, I read some lines from the file.
string f3 = "temp.txt";
string r;
string temp;
infile.open (f3.c_str ());
while (getline (infile, r)) {
// b is take from above
temp = r + b;
cout << temp << endl;
}
// The above would give me the wrong concatenation.
// Say the first line in temp.txt is **quickly**.
// The output after reading the line and concatenating is **worldly**
Hope it gives more clear example.
Update:
I think I may have found out that the problem is due to the text file. I tried to create a new text file with some random lines inside, and it seem working fine. But if I try to read the original file, it gives me the wrong output. Still trying to put my head around this.
Then I tried to copied the content of the original file to the new file, and it seem to be working fine. Not too sure what is wrong here though. Will continue to test out, and hopefully it works fine.
Thanks for all the help! Appreciate it!
I get the same output as the chap who asked the original question:
$ ./a.out hello world
Enter code: good
goodworld
worldly
The problem here is the contents of the text file. For my example, the initial 7 characters in the text file are: "quickly". However, immediately following that are 7 backspace bytes (hex 08). This is what the contents looks like in emacs:
quickly^H^H^H^H^H^H^H
So how is this causing the mess?
Well the concatenation operation actually works correctly. If you do:
std::cout << "string length: " << temp.size() << "\n";
...you get the answer 19 which is made up of: "quickly" (7) + 7 backspace chars + "world"(5). The overwriting effect you observe is caused when you print this 19 char string to console: it is the console (eg xterm) that interprets the backspace sequence as meaning "move the cursor back to the left", thus removing earlier characters. If instead you pipe the output to file, you will see the full string (including the backspaces) is actually generated.
To get around this you might want to validate/correct the input that comes from the file. There are functions commonly available in C/C++ environments such as isprint(int c), iscntrl(int c) that you could make use of.
Update: as mentioned by another responder, other ASCII control characters will also have the same effect, eg, a carriage return (Hex 0D) will also move the cursor back to the left.
If I compile this
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main (int nArgs, char *zArgs[]) {
string a = string (zArgs [1]);
string b = string (zArgs [2]);
string code;
cout << "Enter code: ";
cin >> code;
string concat = code + b;
// The output above gives me the correct concatenation.
//However, I read some lines from the file.
ifstream infile;
string f3 = "temp.txt";
string r;
string temp;
infile.open (f3.c_str ());
while (getline (infile, r)) {
temp = r + code;
cout << temp << endl;
}
// The above would give me the wrong concatenation.
infile.close();
return 0;
}
it compiles and runs flawlessly. What does this do on your computer? If it fails, we may have to compare the contents of our temp.txt.
(This ought to be a comment rather than an answer, but it's too long. Sorry.)
I am trying to read a file line by line using the code below :
void main()
{
cout << "b";
getGrades("C:\Users\TOUCHMATE\Documents\VS projects\GradeSystem\input.txt");
}
void getGrades(string file){
string buf;
string line;
ifstream in(file);
if (in.fail())
{
cout << "Input file error !!!\n";
return;
}
while(getline(in, line))
{
cout << "read : " << buf << "\n";
}
}
For some reason it keeps returning "input file error!!!". I have tried to full path and relative path (by just using the name of the file as its located in the same folder as the project). what am I doing wrong?
You did not escape the string. Try to change with:
getGrades("C:\\Users\\TOUCHMATE\\Documents\\VS projects\\GradeSystem\\input.txt");
otherwise all the \something are misinterpreted.
As Felice said the '\' is an escape. Thus you need two.
Or you can use the '/' character.
As windows has accepted this as a directory separator for a decade or more now.
getGrades("C:/Users/TOUCHMATE/Documents/VS projects/GradeSystem/input.txt");
This has the advantage that it looks much neater.
first, if you wanna say '\' in a string, you should put '\\', that's the path issue.
then, the string buf is not in connect to your file..
The backslash in C strings is used for escape sequences (e.g. \n is newline, \r carriage return, \t is a tabulation, ...), thus your string is getting garbled because for each backslash+character sequence the compiler is replacing the corresponding escape sequence. To enter backslashes in a C string you have to escape them, using \\:
getGrades("C:\\Users\\TOUCHMATE\\Documents\\VS projects\\GradeSystem\\input.txt");
By the way, it's int main, not void main, and you should return an exit code (usually 0 if everything went fine).
I am trying to write a little program that will load in a file, compare each line with a specific array of words, and if that line has any of those words in it then I want to "print" that line out to a file.
My current code is:
int main()
{
string wordsToFind[13] =
{"MS SQL", "MySQL", "Virus", "spoof", "VNC", "Terminal", "imesh", "squid",
"SSH", "tivo", "udp idk", "Web access request dropped", "bounce"};
string firewallLogString = "";
ifstream firewallLog("C:\\firewalllogreview\\logfile.txt");
ofstream condensedFirewallLog("C:\\firewalllogreview\\firewallLog.txt");
if(firewallLog.fail())
{
cout << "The file does not exist. Please put the file at C:\\firewalllogreview and run this program again." << endl;
system("PAUSE");
return 0;
}
while(!firewallLog.eof())
{
getline(firewallLog, firewallLogString);
for(int i = 0; i < 13; i++)
{
if(firewallLogString == wordsToFind[i])
{
firewallLogString = firewallLogString + '\n';
condensedFirewallLog << firewallLogString;
cout << firewallLogString;
}
}
}
condensedFirewallLog.close();
firewallLog.close();
}
When I run the program it will compare the string, and if it matches it will only print out the specific word instead of the string. Any help would be much appreciated.
If I understand your problem correctly, you want to check if the line contains one of the word and print it if it does.
Right now what you are doing is this:
if(firewallLogString == wordsToFind[i])
Which checks if the string exactly matches the word. So, if the string contains one of the word but has other words in it, the test will fail.
Instead, check if the word is part of the string, like this:
if(firewallLogString.find(wordsToFind[i]) != string::npos)
There is something wrong in your code.
in this line
getline(firewallLog, firewallLogString);
you are reading a line, not a word, but then later you are comparing the whole line with a word from your array. Your IF shall not work actually.
Instead you need to use strstr method, to lookup for any word in your firewallLogString and if it finds you do the rest of your code.
Use std::string's find method to find the occurrence of your pattern words.