Hello, i'd like to make a program which reads input until end of file on standard input and when i press ctrl-d (or i'm not sure how to end it) it writes out the lines which contain a string.

so if i start with :

./a.out cond

First line
Second line
Third line

it should write out:

Second line

and if i just do ./a.out it should write out all lines.


What i could do so far:

#include <iostream>
#include <string>

using namespace std;

int main()
{
   string str;
    char Char;
    while (!cin.eof())
    {
        cin.get(Char);
        str += Char;
    }
    cout << str;
    return 0;
}

I don't understand what about "cond" makes it output the second line? (did you mean "second"?) How would you output the first?

You'll have to take in arguments from the command line (look up "argc and argv" for lots of examples).

Edited 5 Years Ago by jonsca: n/a

I mean if the line contains "cond" from second or other words then it should write out only the lines that contains "cond" after ctrl-d.

Gotcha.

I'm assuming you're not allowed to use getline. I would read until you hit a '\n' and check the line. If it contains the substring, print it right out. If not, clear the string and start again.

Did you look up how to get arguments from the command line?

I tried this but i don't know how to tell it to write out only the line which contains the "cond".

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    string str;
    string str2;
    char Char;
    	
    while (!cin.eof())
    {
        cin.get(Char);
        str += Char;
        for(int i=0; i<argc; ++i)
        {
           string str2 = argv[i];
       
	   if(str=="cond")
           cout << str << endl;
       }
    }

    cout << str;
    return 0;
}

It writes out the char position now for the arg but i don't know what to replace size_t with to write out the entire line.

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    string str;
    string str2; 
    char Char;
    size_t found;    
	
    while (!cin.eof())
    {
        cin.get(Char);
        str += Char;
    }

    for(int i=0; i<argc; ++i)
    {
       str2 = argv[i];
       found = str.find(str2);

	if(found !=string::npos)
       cout << found << endl;
    
    }

    return 0;
}

Edited 5 Years Ago by jacob07: n/a

Why do you need the loop on line 19? argv[0] just contains the name of the executable. If you want the last argument go to argv[argc-1] .

This is where I was saying that you should read into str up until you hit a '\n', then do your find(), print it out if the substring is in there, then clear out str for the next line.

read into str up until you hit a '\n', then do your find(), print it out if the substring is in there, then clear out str for the next line

I have no idea how to do that.

You'll have to shift your while loop around to encompass the information that was in your for loop

while(not at the end of the file, read in a char)
{
   if that char is not '\n'
       add it to the string
   else
       //line is done
       check to see if the substring is in the string
       if(so)
           print it out
       else
           clear the string and continue on
}
Comments
Nice pseudocode

I only get numbers as results, i don't understand.

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    string str;
    string str2; 
    char Char;
    size_t found;    
	
    while (!cin.eof(), cin.get(Char))
    {
        if(Char!='\n'){
             str += Char;
	 }else{
    	      str2 = argv[argc-1];
      	      found = str.find(str2);}
    
    		if(found !=string::npos){
		   cout << found << endl;}
    		else{
		   cout << str;}
     }
    return 0;
}
while((Char = cin.get())!=EOF)

This is getting Char (consider changing that name as it's rife with possibilities for typing in "char" by mistake) as an integer so it can be compared with EOF. You will probably need to cast it to a char before you tack it onto str.

Why are you outputting found? found is only going to give you the position in the string. Do what your originally specified, if found is true, output the whole string, otherwise clear the string out for the next line. If you don't clear str out, you're going to end up with everything you've ever input in it.

It doesn't want to write out the strings when i press ctrl-d. If i put out the if-else from the while loop it writes out but doesn't check the find().

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    string str;
    string str2; 
    char Char;
    size_t found;    
	
    while ((Char = cin.get())!=EOF)
    {
        if(Char!='\n'){
             str += Char;
	 }else{
    	      str2 = argv[argc-1];
      	      found = str.find(str2);}  		
     
	
     if(found !=string::npos){
	   cout << str;
     	   }
     else{  
	   str.clear();
	   cout << str;
	   
	  }
    }
    return 0;
}

Part of the reason you're getting numbers is that cin.get() returns an int (it has to because it can return EOF, which is normally a negative number). So "Char" the variable should be an int. I've run into a problem which I always hate, in that you have to hit EOF (ctrl-z on Windows, and ctrl-d on *nix) twice to get it to work.

The other element I think you need to get it to work is to use an array of strings to hold the lines as they came in. That way you can print them at the end. I was trying to help you print them after they were entered but I don't think that's what your specification wants.

Check around for some other examples related to this, give it some more shots, and see what you come up with.

I tried to use str.push_back, it worked a bit but when i press ctrl-d it writes the strings into one line instead of multiple:

first
second
third

will be:
first
secondthird

you need to get it to work is to use an array of strings to hold the lines as they came in

How do you do that?

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    string str;
    string str2; 
    char Char;
    size_t found;    
	
    while ((Char = cin.get())!=EOF)
    {
        if(Char!='\n'){
             str += Char;
             str.push_back(cin.get());

	 }else{
    	      str2 = argv[argc-1];
      	      found = str.find(str2);}  		
     	
     if(found !=string::npos){
           str.push_back(cin.get());
	   cout << str;
     	   }
     else{  
          str.push_back(cin.get());
	  cout << str;
   
	  }
    }
    return 0;
}

Why are you trying to output your string on line 29? If you haven't found the substring that you've supplied, just throw it away.

Also, note that you are getting a new character on lines 17,24 and 28, which you should only get one character once through the loop (on line 13)

How do you do that?

//early on
int i=0;
string arr[10]; 
//later in the program
arr[i] = str;
i++;

Edit: To get the EOF to work properly, instruct your users to hit enter at the end of the last line, do the ctrl-z, then hit enter.

Another hint, start a fresh program, and try at first to get the lines and simply output them. Then you can add in the other functionality later.

Edited 5 Years Ago by jonsca: n/a

I think i need to tell it if it finds the argument then search for '\n' before and after the argument then write out what's between two '\n'-s but i don't understand how.

See if you can do what I suggested, take each line from the user and put it in an array of strings. Don't worry about the other stuff, that's just a small step if you have the strings.

So, read character by character into a single string, once you hit a newline, copy that single string into your array of strings.

Make sure you change the type of your variable "Char" to be an int, as that's the only way it's going to work out with EOF.

You mean like this?

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
	int i=0;
	string arr[10];
	string str;
	int Char;
    
    	while ((Char = cin.get())!=EOF)
    	{
            	  str += Char;
	}	
	
	arr[i]=str;
	i++;	
     	cout << str;
	return 0;
}

If i put if(Char!='\n'){str += Char;} then it write out everything into one line:
1
2
3
will be: 123

You're closer, you want to put the string into the array only when the user has pressed enter:

if (c == '\n')
{
   //add str to the array
   //clear out str for the next line
   //increment i
}
else
   str+=Char;  //if we haven't hit a newline, keep adding.

You tested whether your code is working, but you also need to be able to see what's wrong.

Then, after the loop is complete, search your way through the string array and see if you find your substring. If so, print out the entire line.

Now when it finds the string, str.clear() deletes the line that contains it and previous lines and only writes out the lines which are after

first line
second line
third line

third line

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
	int i=0;
	string arr[10];
	string str;
	string str2;
	int Char;
	size_t found;

    	while ((Char = cin.get())!=EOF)
    	{
            	str2 = argv[argc-1];
		found = str.find(str2);  
		
		if(Char=='\n' && found!=string::npos)
		{
			arr[i]=str;
			str.clear();
			i++;
     		
		}else{
			str+=Char;}
	}	
	cout << endl << str;
	
	return 0;
}

The whole idea of writing the strings into the array was that you could scan through the set of strings for your substring after you had read all of the strings in. Do only the scanning within the loop.

Move 17 outside of the loop (it can even go before the while loop if you want).

Also move line 18 out, but change it to step through your string array (hint: a loop will be necessary) and print out the strings that match.

I've nudged you along here, but you need to be able to do some of your own debugging. If the code isn't doing what you want it to, put some statements in there to output your variables at intermediate points to see what's going on -- or use a debugger.

Edited 5 Years Ago by jonsca: n/a

Also move line 18 out, but change it to step through your string array

I don't know how to do that.

but change it to step through your string array

Can you show me an axample for this? I'm totally lost.

string arr[] = {"step","through","the","array"}; //obviously your array will be whatever you loaded up in the loop
for (int i = 0;i<4;i++)
{
   //do something with arr[i] here
}

Edited 5 Years Ago by jonsca: n/a

I don't understand how to put found = str.find(str2); into the for loop.

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
	int i=0;
	string arr[10];
	string str;
	string str2;
	int Char;
	size_t found;
	str2 = argv[argc-1];
	
	for(int i=0;i<10;i++)
	{
		if(Char=='\n'){ 
		arr[i]=str;
		str.clear();}
		
	}

	while ((Char = cin.get())!=EOF)
    		{         	  

		
		if(found!=string::npos)
		{	
			found = str.find(str2);
			cout <<str;				
			
		}else{
			str+=Char;}
		}
	cout << endl << str;
	
	return 0;
}

What does str contain on line 19?

It seems like you are just guessing at what to code at this point. I'm honestly not sure how to direct you so this makes sense to you (as I'm not going to do it for you). I did specify that your looping and checking should come after the forming of the lines. Does it make sense to do so before? Especially when str is empty...

While(take in char)
{
   if the char is a '\n', this is a complete line, add it to our array and clear it
   
   else, tack it onto the end of the line.
}

for(over all of the lines of the array, i)
{ 
   if(string[i] contains str2)
      print it out
   [otherwise, do nothing]
}

Go through the different steps and convince yourself this is a logical way to do things.

This article has been dead for over six months. Start a new discussion instead.