For loop to input strings in vector using getline - c++

So I have an assignment for school, I need to declare a vector of strings
then use a for loop to input names into the vector using get line. This code is what I have so far, I was trying to make a variable for a location in my vector, then input a string into the vector based on the value of my variable. Im using C++.
What Im wondering is: whats the flaw in my logic?
#include "stdafx.h"
#include <iostream>;
#include <vector>;
#include <string>;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector<string> name_list(10);
int n;
for (name_list[n]; cin.getline >> name_list[n]; ++n)
cin >> name_list[n];
cout << name_list[n];
int stop; cin >> stop;
return 0;
}
EDIT:::
So I figured it out! Thank you 0x499602D2, You kinda set me on the right way. the code I came up with is this::
int _tmain(int argc, _TCHAR* argv[])
{
vector<string> name_list(11);
int n = 0;
for (int n = 0; n < 11; ++n);
getline(cin, name_list[n]);
cout << name_list[n];
int stop; cin >> stop;
return 0;
}

Not only is n uninitialized, you're also doing cin.getline >> name_list[n] which shouldn't even compile as far as I know. getline is a member function of std::cin that reads a line from input into a character array. It's not needed here as we are trying to read into a vector.
Moreover, since you want to get names from the user input into each slot in the vector, attempting to retrieve a line with getline also wouldn't make sense.
n needs to be initialized to an integer that when access with name_list[n], will give us the start of the vector (that would be 0), and instead of getline, we use the operator >> to get each whitespace separated input. Like this:
for (int n = 0; std::cin >> name_list[n]; ++n)
; // empty
A statement isn't needed within the for loop body as its already been done in the loop parameters.
Another thing you need to look out for is overrunning the size of the vector. You initialized name_list with a size of 10, and if the user enters in, say, 11 names, accessing an index with name_list[n] will cause Undefined Behavior in your program, which is a special way of saying your program will be invalid.
It's better to use the at() member function as it will throw an exception if you try to access an out-of-bounds address:
for (int n = 0; std::cin >> name_list.at(n); ++n)
// ^^^^^^
;

You need to initialize n=0 and in the second for parameter you might wanna move the cin into the loop and replace it with i < 10 because otherwise the loop would not know when to stop

Related

Segmentation Fault while accepting input

I am trying to accept the input from user
where first line will be Integer to indicate number of testcases
if number is 3
Input will be like
3
Hello world
hey there, I am John
have a nice day
I am using getline to read the input
My code
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n;
cin >> n;
vector<string> arr;
for(int i=0; i<n; i++){
string s;
getline(cin, s);
arr[i] = s;
}
}
Error:
3
Segmentation fault(core dumped)
arr is an empty vector, so arr[i] = s; is going to access out of bounds. The [] operator does not grow the vector. It can only be used to access already existing elements.
You can't create an element of a vector using the [] indexing operator; your line arr[i] = s; is trying to assign a string to an element that doesn't (yet) exist.
There are several ways around this: first, you could use the push_back function to add a new element to the end of the vector, in each loop; second, you could use the resize member to pre-allocate a specified number of elements (which you can then use in the arr[i] = s; line); third - and perhaps simplest - you can 'pre-allocate' the elements of the vector by specifying the number of elements in the declaration (constructor), like this:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string> // Need this for the "getline()" function definition
using namespace std;
int main()
{
size_t n; // Indexes and operations on std::vector use "size_t" rather than "int"
cin >> n;
cin.ignore(1); // Without this, there will be a leftover newline in the "cin" stream
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // More precise, actually!
vector<string> arr(n);
// arr.resize(n); // Alternative to using 'n' in constructor
for (size_t i = 0; i < n; i++) {
string s;
getline(cin, s);
arr[i] = s;
}
for (auto s : arr) cout << s << endl; // Just to confirm the input values
return 0;
}
There are also a few other issues in your code that I have 'fixed' and commented on in the code I posted. Feel free to ask for further clarification and/or explanation.
EDIT: On the use of the cin.ignore(1); line I added, see Why does std::getline() skip input after a formatted extraction? (and the excellent answers given there) for more details.

Reading a row until newline in the console

I need to make a program that reads n numbers in a row. For example, the user first puts in a list of 2 numbers like this:
P n
I managed to read those with scanf but now I need to read the n following numbers, these numbers are given in a row as follows.
1 6 3 99 ... n times
These numbers must be read all at once (or give the impression of).
I already tried using
while(getline(cin,str)){
// do something with str
}
As explained in this thread but I need the actions inside the while loop to stop when I hit the intro key. With my current implementation they don't stop, it just keeps waiting for more lines to read.
In summary:
First, user must be able to input two numbers (P and n)(done!) then hit enter and start typing a list of n numbers (not done!).
Here is my code.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main(void){
int P,n;
scanf("%d %d",&P,&n);
string val;
int score[P];
int i;
for(i=0;i<P;i++){
score[i]=0;
}
while(getline(cin,val)){
printf("Val=%s\n",val.c_str());
stringstream stream(val);
int local;
while(stream >> local){
score[local]=score[local]+1;
printf("%d-%d\n",local,score[local]);
}
}
for(i=0;i<P;i++){
printf("%d-%d\n",i,score[i]);
}
return 0;
}
Use scanf() inside the n times loop instead of getline().
for(int i = 0; i < n; i ++){
scanf("%d",&variable);
}
Not sure I understood your question, but this code will read 2 numbers, then a line and then finish.
using namespace std;
int main(){
int P,n;
cin >> P;
cin >> n;
int *score = new int[P];
for(int i=0;i<P;i++){
score[i]=0;
}
int num;
string val;
cin.ignore();
getline(cin, val);
istringstream stream(val);
while (stream >> num) {
printf("Val = %d\n", num);
score[num]=score[num]+1; // potential segmentation fault here in your code
printf("%d-%d\n",num,score[num]);
}
delete [] score;
return 0;
}
The fault would occur because you are assuming that the number on the line is smaller than P, which is the size of the array. However, the following input would cause error:
1 2
5
This question is almost a classic. The classic question has this code:
cin >> n;
getline(cin, s);
and then the author is puzzled why s is empty. Your variation does the same, although it also uses C stdio function to make matters more confusing. The problem is that the first call is a field-based input, which will read a single value n and leave any other input in the buffer! If the user entered 42 and hit enter, the remaining input is the newline. The second getline() call then reads an empty string and discards the newline.
For interaction with the user, only use getline() and then try to parse each line. Using stringstreams or sscanf(), since you seem familiar with it, are both valid options. However, if you only want to read the input an not really interact, David Weston's suggestion is also a good one and probably the easiest one, too. However, since you're using C++, I'd suggest using cin >> variable instead.

c++ word count(as words we take every possible variable name)

I was asked to make a program that reads a cin could be text and then counts the words in it(i need to count as a word every name that can be accepted as a variable name ex _a,a1) my problem is that my code works for only one byte. if its more than one the sum is always 0.The only thing i think i can have wrong is that i didn't put the string into an array but a friend of mine told me i don't need to do so.below is my code:
#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
int main(){
int sum=0;
bool z= false; //z is just a switch to see if we are inside a word\n
string s;
cout<<"Insert text: ";
getline(cin,s); //here we get the string\n
int n=s.length()-1; //for some reason i==(s.length-1) put a warning$
for(int i=0;i==n;i++){ //here we check each byte to see what it contai$
cout<<s[i];
if(isalpha(s[i]) || s[i]=='_'){ //to enter a word we need a let$
z=true;
sum++;}
if(z==true){ // if we are in a word we can have numbers as w$
if(!isalnum(s[i]) && s[i]!='_'){
z=false;}} // exit the current word and go$
if(s[i]==EOF){ // the end\n
break;}}
cout<<"Number of words is: "<<sum<<endl; // the real end\n
return 0;
}
This is so much easier than the code you have provided. We can do this with the STL using an istream iterator. If you choose to use C++ and not C, then you should take advantage of the standard library.
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
using namespace std;
int main(){
vector<string> words((istream_iterator<string>(cin)), istream_iterator<string>());
for(int i = 0; i < words.size(); i++)
cout << words[i] << '\n';
return 0;
}
Check your for loop.. it runs as long as the second statement is true.. when is it true that i==n? only at the very last byte.. change this to i<=n instead.
First of all you don't need dont use getline because it is insecure, use cin instead. Also you do not need the and use cin instead of getline. Also if getline is used with an array it could pose a serious problem and could be exploited via stack overflow. Sorry I cant help much what you were asking but I just wanted to give you a heads up.

input in c++ - cin.getline

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int T;
char J[100], S[100];
int count=0;
cin >> T;
while(T--)
{
cin.getline(J,100);
cin.getline(S,100);
puts(J);
puts(S);
for(int i=0; J[i]!='\0'; i++)
{
for(int j=0; S[j]!='\0'; j++)
{
count++;
for(int k=j; S[k]!='\0'; k++)
S[k]=S[k+1];
break;
}
}
cout << count;
}
return 0;
}
I am taking input string in J,S but during execution of program it skips the second input from the console cin.getline
I takes the test cases then takes the Strings J and S
it takes J successfully but fails to get S string ?
you need to be using a string , std::string, and calling getline as in
std::string s,j;
std::getline(std::cin,j);
std::getline(std::cin,s);
and then if you want to iterate over the contents of the strings by individual characters
for(auto i = std::begin(s); i != std::end(s); ++i)
{
std::cout << *i << std::endl;
}
use the iterators, and deference them to get the actual character values. Stay way from c strings as much as possible.
This code:
int T;
// ...
cin>>T;
...reads an int from standard input. To get it to read that int, you need to press the enter key, but this code does not remove that enter from the input buffer. Then...
cin.getline(J,100);
This tries to read a string from the input buffer, up to the first new-line character. It removes that new-line from the input buffer, but does not include it as part of the string. As such, if you don't look really closely, it appears to do essentially nothing -- i.e., you end up with an empty string.
You generally want to stick to either field-oriented input (like your cin >> T; or else line-oriented input (getline). Mixing the two, however, can be a bit tricky, especially if the getline comes after the field-oriented input. Don't get me wrong: it can work -- and work perfectly well at that, but you need to know what you're doing, and even then it can still surprise you now and again.
As noted in my comment (and #johnathon's answer) you also generally want to use std::getline to read an std::string, instead of std::cin.getline with an array of char. The latter is clumsy to deal with, even at best.
My own preference is (as a rule) to use line-oriented input throughout if you're going to use it anywhere.
std::string temp;
std::getline(std::cin, temp);
int T = lexical_cast<int>(temp);
while (T--) {
std::string j;
std::getline(std::cin, j);
// ...
As an aside, I'd also avoid using T as a name of an ordinary variable in C++. It's quite commonly used as the name of a template parameter; using it for "normal" variables is more likely to lead to confusion, especially for more advanced programmers who use templates more often.
(1)Use getchar() between cin>>T and while (T--)
as
int T;
char J[100] , S[100];
int count=0;
cin>>T;
getchar();
while(T--){
cin.getline(J,100);
cin.getline(S,100);
(2).
You can also resolve your problem in following way::
char T[10];
char J[100] , S[100];
int count=0;
getline(T,10);
while((atoi(T))--){
cin.getline(J,100);
cin.getline(S,100);
use Any 1 of them ,it will fix your problem.

how to read character data using cin to store in an array and display?

I am writing a simple console application to read 3 words and keep them in an array. But after taking three inputs from the console it only displays the third word three times in the console. For example, if I give the input: "one", "two" "three" the output shows only "three" 3 times).
Here is my code:
int main(int argc, char *argv[])
{
char* input[30];
char word[30];
int i=0;
for(i=0; i<3 ;++i)
{
cin >> word;
input[i] = word;
}
input[i] = 0;
i=0;
while(input[i])
{
cout << input[i] << endl;
i++;
}
return 0;
}
What I am doing wrong here? Thanks for any help.
You only have one buffer ( char word[30] ), which you are overwriting each time.
When you do:
input[i] = word;
You're assigning the address of the first element in that one and only buffer to each element in input (arrays degrade to pointers when you use the bare name). You end up with three copies of the same address in input[] (which is address of word, which contains the last thing your read from cin)
One approach to fix this would be to use strdup() and assign the newly allocated string to your input[i]
for(i=0; i<3 ;++i)
{
cin >> word;
input[i] = strdup(word);
}
Also ... if you only are going to have three input "words" you only need an array of 3 char pointers:
char *input[3];
and your output loop would look much like your input loop:
for(i=0; i<3 ;++i)
{
cout << input[i] << endl;
}
Edit: Note that this answer was based on your wanting to use arrays. If this isn't homework that requires that, see bobbymcr's answer - when in C++, use C++.
You marked your question as "C++" (not "C") so I will recommend that you actually use C++ idioms to do this. Modern programs should not be using raw char arrays and pointers except for low level programming and interoperability with legacy or barebones C APIs.
Consider using string and vector as they will make your life much easier. Here is a reimplementation of your program using these types. Aside from the iterator stuff (which I admit is a bit strange until you get used to it), it should seem a lot clearer than the equivalent using char *, etc.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(int argc, char ** argv)
{
vector<string> input;
for (int i = 0; i < 3; ++i)
{
string word;
cin >> word;
input.push_back(word);
}
for (vector<string>::const_iterator it = input.cbegin(); it != input.cend(); ++it)
{
cout << *it << endl;
}
return 0;
}
The problem is here:
char* input[30];
You maybe tempted to think that this is array of character array, but in essence it's not.
You would either need to dynamically allocate space for the array, or simply use two dimensional character array(fixing the max number of words that you can have).
char input[30][30]; // maximum 30 words having at most 29 characters each