I am trying to get input data from a txt file on Linux / Mint. So, after compiling the code I run the following command: ./a.out output.txt
I need to fill a two-dimensional array but like a jagged array (the number of columns in each row is different). So I want to split it by looking character what is read from file. If the character is '\ n', I want to fill the second line. But I guess I can not read the '\ n' character. I hope I can explain the problem.
I'm writing the code, maybe it will be more clearer.
my input.txt file is:
my c++ code part is for getting input:
for (int i = 0; i<n; i++) {
char ch;
cin >> ch;
int j = 0;
while (ch != '\n') {
arr[i][j] = ch;
cin >> ch;
j++;
}
}
I want to that, if the character is equals the '\n' then program goes on to fill the array to next row.
arr[0][0] = 'a';
arr[0][1] = 'f'
arr[0][2] = 'h'
arr[1][0] = 'b'
arr[1][1] = 'e'
arr[1][2] = 'g'
arr[2][0] = 'c' .......)
When you do cin >> ch it will skip whitespace, which includes spaces, tabs and newline characters. Perhaps, you need to read entire lines using std::getline, and then process each line separately.
For example:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
char ch;
std::string line;
int ln = 0;
while (getline(cin, line)) // read entire line
{
istringstream is;
is.str(line);
while (is >> ch) // now read individual chars from that line
cout << "line: " << ln << " char: " << ch << endl;
ln++;
}
}
And your loop should be something like this:
std::string line;
for (int i=0; i<n; ++i)
{
char ch;
if (!std::getline(cin, line))
break;
std::istringstream is;
is.str(line);
for (int j=0; is >> ch; ++j)
arr[i][j] = ch;
}
You omitted details on how you declare your arr, but it doesn't seem like the code you've shown would handle it properly. Perhaps, it would be better to use vectors:
std::vector<std::vector<char> > arr;
std::string line;
char ch;
while (std::getline(cin, line)) // cin should probably be replaced with ifstream
{
std::istringstream is;
is.str(line);
arr.push_back(vector<char>());
for (int j=0; is >> ch; ++j)
arr.back().push_back(ch);
}
Related
#include <iostream>
using namespace std;
int main()
{
int n,t=0,k=0;
cin>>n;
char data[n][100];
int num[n];
for(int i=0;i<n;i++)
{
while(1)
{
cin>>data[i][t];
cout<<data[i][t]<<endl;
if(data[i][t]=='\n') break;
k++;
if(k%2==1) t++;
}
cout<<i;
num[i]=(t-2)/2;
k=0;
t=0;
}
for(int i=0;i<n;i++)
{
while(1)
{
cout<<data[i][t];
if(t==num[i]) break;
t++;
}
t=0;
}
}
here is the code I have written in c++ which gives the even numbered characters from the starting half of every word given by the user but when giving input after pressing enter the loop should break but the loop is not breaking
while(1)
{
cin>>data[i][t];
cout<<data[i][t]<<endl;
if(data[i][t]=='\n') break;
k++;
if(k%2==1) t++;
}
By default formatted input using the "input" operators >> skip white-space, and newline is a white-space character. So what's happening is that the >> operator simply waits for some non-white-space input to be entered.
To tell the input to not skip white-space you have to use the std::noskipws manipulator:
cin>>noskipws>>data[i][t];
There are some ways to implement in C++ what OP is trying to do. I'd start avoiding Variable Length Arrays, which aren't in the Standard and using std::strings and std::vectors instead.
One option is to read an entire line from input with std::getline and then process the resulting string to keep only the first half of even chars:
#include <iostream>
#include <string>
#include <vector>
int main() {
using std::cin;
using std::cout;
using std::string;
cout << "How many lines?\n";
int n;
cin >> n;
std::vector<string> half_words;
string line;
while ( n > 0 && std::getline(cin, line) ) {
if ( line.empty() ) // skip empty lines and trailing newlines
continue;
string word;
auto length = line.length() / 2;
for ( string::size_type i = 1; i < length; i += 2 ) {
word += line[i];
}
half_words.push_back(word);
--n;
}
cout << "\nShrinked words:\n\n";
for ( const auto &s : half_words ) {
cout << s << '\n';
}
return 0;
}
Another is, as Joachim Pileborg did in his answer, to disable skipping of leading whitespaces by the formatted input functions with std::noskipws manipolator and then read a char at a time:
// ...
// disables skipping of whitespace and then consume the trailing newline
char odd, even;
cin >> std::noskipws >> odd;
std::vector<string> half_words;
while ( n > 0 ) {
string word;
// read every character in a row till a newline, but store in a string
// only the even ones
while ( cin >> odd && odd != '\n'
&& cin >> even && even != '\n' ) {
word += even;
}
// add the shrinked line to the vector of strings
auto half = word.length() / 2;
half_words.emplace_back(word.begin(), word.begin() + half);
--n;
}
// ...
#include<sstream>
#include<iostream>
using namespace std;
int main(){
string line = "test one two three. \n another one \n";
string arr[8];
cout<<line;
int i = 0;
stringstream ssin(line);
while (ssin.good() && i < 8){
ssin >> arr[i];
++i;
}
for(i = 0; i < 8; i++){
cout << arr[i];
}
return 0;
}
//Now i want to print that elements that just come before the newline ("\n") in the string.
Don't think of "test one two three. \n another one \n" as one line of text. It is not. It is two lines of text.
You need to change your strategy of reading a little bit.
int main()
{
string input = "test one two three. \n another one \n";
string arr[8];
int i = 0;
stringstream ssin_1(input);
string line;
// Read only the tokens from the first line.
if ( std::getline(ssin_1, line) )
{
stringstream ssin_2(line);
while ( ssin_2 >> arr[i] && i < 8)
{
++i;
}
}
// Don't print all the elements of arr
// Print only what has been read.
for(int j = 0; j < i; j++){
cout << arr[j] << " ";
}
return 0;
}
Your ssin >> arr[i] skips whitespace, losing all knowledge of which arr entries were followed by newlines.
Instead, you can divide input into lines first, then words, while tracking the newlines:
std::vector<size_t> newline_after_word_index;
std::vector<std::string> words;
while (getline(ssin, line))
{
std::istringstream line_ss(line);
std::string word;
while (line_ss >> word)
words.push_back(word);
newline_after_word_index.push_back(words.size());
}
You can then use indices from newline_after_word_index to print out the words[] entry beforehand....
http://www.cplusplus.com/reference/string/string/find/
#include<sstream>
#include<iostream>
using namespace std;
int main(){
string line = "test one two three. \n another one \n";
size_t found = line.find("\n");
for (int i=0; i<=found; i++){
cout << line[i];
}
return 0; }
I am trying to read a single character multiple times. The catch is that I need to prevent user errors. So for example:
char arr[10];
for(int i = 0; i < 10; i++)
{
cin.get(arr[i]);
}
Where the inputs should be something like a, b, c, d, .... But if someone were to enter ab for the first entry I want to capture the a and then ignore the b. I know about cin.ignore however I don't know how I would go about ignoring an arbitrary number of alphanumeric characters or symbols considering that I want to ignore a potentially unlimited number of characters and then stop ignoring and read again.
How can I either ignore an arbitrary number of characters and then stop ignoring or how can I actually flush the buffer for cin.
Most input is line feed so if you want to ignore all characters in the input stream until you hit a newline then you could use:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
Since we ignore up to the streamsize there should not be an extra content in the input buffer.
If you want user to hit enter after each symbol, then code could be as simple as this:
char arr[10];
for(int i = 0; i < 10; )
{
std::string line;
std::getline( std::cin, line );
// check that line is not empty
if( line.empty() ) {
std::cout << "missing input" << std::endl;
continue;
}
arr[i++] = line[0]; // get only first symbol and ignore the rest
}
if you have something else in mind, I am afraid that will not work with std::cin - you do not see any input until user presses enter. In that case you would have to use OS specific functions to get unbuffered input.
The following is the code that you want, if your inputing like this a 'enter' b 'enter' c 'enter' etc...
#include <iostream>
#include <string>
using namespace std;
int main() {
char arr[10];
string line;
for (int i = 0; i < 10; i++)
{
getline(cin, line);
arr[i] = line[0];
cout << endl << "Here is the Char: " << arr[i] << endl;
}
return 0;
}
BUT if you enter input like this in one line: a,b,c,d,e,f,g,h,i,j 'enter' then you want the following code:
#include <iostream>
#include <string>
using namespace std;
int main() {
char arr[10];
string line;
int i = 0;
size_t end;
getline(cin, line);
end = 0;
int counter = 0;
if (line != "") {
while (end != string::npos && counter < 10) {
if (counter == 0) {
arr[counter] = line[0];
}
else {
end = line.find(",", end + 1);
arr[counter] = line[end + 1];
}
counter++;
}
}
for (int i = 0; i < 10; i++) {
cout << endl << "Here is the Char: " << arr[i] << endl;
}
return 0;
}
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int hmlines(ifstream &a){
int i=0;
string line;
while (getline(a,line)){
cout << line << endl;
i++;
}
return i;
}
int hmwords(ifstream &a){
int i=0;
char c;
while ((c=a.get()) && (c!=EOF)){
if(c==' '){
i++;
}
}
return i;
}
int main()
{
int l=0;
int w=0;
string filename;
ifstream matos;
start:
cout << "give me the name of the file i wish to count lines, words and chars: ";
cin >> filename;
matos.open(filename.c_str());
if (matos.fail()){
goto start;
}
l = hmlines(matos);
matos.seekg(0, ios::beg);
w = hmwords(matos);
/*c = hmchars(matos);*/
cout << "The # of lines are :" << l << ". The # of words are : " << w ;
matos.close();
}
The file that i am trying to open has the following contents.
Twinkle, twinkle, little bat!
How I wonder what you're at!
Up above the world you fly,
Like a teatray in the sky.
The output i get is:
give me the name of the file i wish to count lines, words and chars: ert.txt
Twinkle, twinkle, little bat!
How I wonder what you're at!
Up above the world you fly,
Like a teatray in the sky.
The # of lines are :4. The # of words are : 0
int hmwords(ifstream &a){
int i;
You've forgotten to initialize i. It can contain absolutely anything at that point.
Also note that operator>> on streams skips whitespace by default. Your word counting loop needs the noskipws modifier.
a >> noskipws >> c;
Another problem is that after you call hmlines, matos is at end of stream. You need to reset it if you want to read the file again. Try something like:
l = hmlines(matos);
matos.clear();
matos.seekg(0, ios::beg);
w = hmwords(matos);
(The clear() is necessary, otherwise seekg has no effect.)
Formatted input eats whitespaces. You can just count tokens directly:
int i = 0;
std::string dummy;
// Count words from the standard input, aka "cat myfile | ./myprog"
while (cin >> dummy) ++i;
// Count files from an input stream "a", aka "./myprog myfile"
while (a >> dummy) ++i;
I'm trying to collect information from a textfile which contains names of organisations (without spaces) and floating integers. I want to store this information in an array structure.
The problem I'm having so far is collecting the information. Here is a sample of the textfile:
CBA 12.3 4.5 7.5 2.9 4.1
TLS 3.9 1 8.6 12.8 4.9
I can have up to 128 different numbers for each organisation, and up to 200 organisations in the textfile.
This is what my structure looks like so far:
struct callCentre
{
char name[256];
float data[20];
};
My main:
int main()
{
callCentre aCentre[10];
getdata(aCentre);
calcdata(aCentre);
printdata(aCentre);
return 0;
}
And the getdata function:
void getdata(callCentre aCentre[])
{
ifstream ins;
char dataset[20];
cout << "Enter the name of the data file: ";
cin >> dataset;
ins.open(dataset);
if(ins.good())
{
while(ins.good())
{
ins >> aCentre[c].name;
for(int i = 0; i < MAX; i++)
{
ins >> aCentre[c].data[i];
if(ins == '\n')
break;
}
c++;
}
}
else
{
cout << "Data files couldnt be found." << endl;
}
ins.close();
}
What I'm trying to achieve in my getdata function is this: store the organisation name first into the structure, then read each float into the data array until the program detects a newline byte. However, so far my check for the newline byte isn't working.
Assume that variables c and MAX are already defined.
How should I go about this properly?
The >> operator treats whitespace as a delimiter, and that includes newlines, so it just eats those and you never see them.
You need to read lines and then chop the lines up. The following bit of hackery illustrates the basic idea:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
string line;
while( getline( cin, line ) ) {
istringstream is( line );
string cs;
is >> cs;
double vals[10];
int i = 0;
while( is >> vals[i] ) {
i++;
}
cout << "CS: " << cs;
for ( int j = 0; j < i; j++ ) {
cout << " " << vals[j];
}
cout << endl;
}
}
char byte = ins.peek();
Or
if(ins.peek() == '\n') break;
(Edit): You'll want to also check for an eof after your peek(), because some files may not have a ending newline.
I'd like to point out that you might want to consider using a vector<callCentre> instead of a static array. If your input file length exceeds the capacity of the array, you'll walk all over the stack.
I would read the file, one line after another and parse each line individually for the values:
std::string line;
while (std::getline(ins, line)) {
std::istringstream sline(line);
sline >> aCentre[c].name;
int i = 0;
while (sline >> aCentre[c].data[i])
i++;
c++;
}