I have a file that looks like this:
e r g d g d
f h d r h f
..........
And I want to store these characters in a two-dimensional array
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ifstream file("file.txt");
char c[20][20];
int i = 0, j = 0;
while(!file.eof())
{
while(!end of line?)
{
file >> c[i][j];
j++;
}
i++;
}
.....
}
how do i do this?
or how to find number of characters in a line?
You can't use eof() like you do. You have to perform an I/O read operation before you can then use eof().
For what you are attempting, you should use std::getline() instead, eg:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <algorithm>
int main()
{
std::ifstream file("file.txt");
std::string line;
char c[20][20] = {};
for (int i = 0; i < 20; ++i)
{
if (!std::getline(file, line))
break;
std::istringstream iss(line);
for(j = 0; j < 20; ++j)
{
if (!(iss >> c[i][j]))
break;
}
}
...
return 0;
}
That being said, you should consider using std::vector instead of fixed-sized arrays (unless you know for a fact that your file will never exceed 20 lines and/or 20 characters per line):
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <vector>
int main()
{
std::ifstream file("file.txt");
std::vector<std::vector<char> > c;
std::string line;
while (std::getline(file, line))
{
std::istringstream iss(line);
std::vector<char> tmp;
std::copy(
std::istream_iterator<char>(iss),
std::istream_iterator<char>(),
std::back_inserter(tmp)
);
/* which is equivalent to:
char ch;
while (iss >> ch) {
tmp.push_back(ch);
}
*/
c.push_back(tmp);
}
...
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <vector>
typedef std::vector<char> CharVector;
std::istream& operator>>(std::istream &in, CharVector &out)
{
out.clear();
std::string line;
if (std::getline(in, line))
{
std::istringstream iss(line);
std::copy(
std::istream_iterator<char>(iss),
std::istream_iterator<char>(),
std::back_inserter(out)
);
/* which is equivalent to:
char ch;
while (iss >> ch) {
out.push_back(ch);
}
*/
}
return in;
}
int main()
{
std::ifstream file("file.txt");
std::vector<CharVector> c;
std::copy(
std::istream_iterator<CharVector>(file),
std::istream_iterator<CharVector>(),
std::back_inserter(c)
);
/* which is equivalent to:
CharVector cv;
while (file >> cv) {
c.push_back(cv);
}
*/
...
return 0;
}
Related
I deleted my old post to be more precise. I'm using c++. I have a csv with ; as separator. With the following code i read a row, then i read all the elements of the row and convert them into int. My problem is that i need to convert them into int16_t or int32_t. The code is:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int main (int argc, const char * argv[]) {
string line, csvItem;
ifstream myfile ("modifica1.csv");
int lineNumber = 0;
int lineNumberSought = 7462;
if (myfile.is_open()) {
while (getline(myfile,line)) {
lineNumber++;
if(lineNumber == lineNumberSought) {
istringstream myline(line);
string bus1s;
string bus2s;
string bus3s;
string bus4s;
string bus5s;
string bus6s;
string bus7s;
string bus8s;
string bus9s;
getline(myline,bus1s,';');
getline(myline,bus2s,';');
getline(myline,bus3s,';');
getline(myline,bus4s,';');
getline(myline,bus5s,';');
getline(myline,bus6s,';');
getline(myline,bus7s,';');
getline(myline,bus8s,';');
getline(myline,bus9s,'\n');
int bus1;
int bus2;
int bus3;
int bus4;
int bus5;
int bus6;
int bus7;
int bus8;
int bus9;
bus1=stoi(bus1s);
bus2=stoi(bus2s);
bus3=stoi(bus3s);
bus4=stoi(bus4s);
bus5=stoi(bus5s);
bus6=stoi(bus6s);
bus7=stoi(bus7s);
bus8=stoi(bus8s);
bus9=stoi(bus9s);
}
}
myfile.close();
}
return 0;
}
Here is an example of how to parse a csv file (with any separator) into a vector of tuples:
#include <sstream>
#include <vector>
#include <string>
#include <tuple>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
template<class... ColumnTypes>
class CsvRowParser
{
char const separator_;
template<size_t... Idxs>
std::tuple<ColumnTypes...>
convert_csv_row(std::vector<std::string> const& columns, std::integer_sequence<size_t, Idxs...>) {
return std::tuple<ColumnTypes...>{boost::lexical_cast<ColumnTypes>(boost::algorithm::trim_copy(columns[Idxs]))...};
}
public:
using RowType = std::tuple<ColumnTypes...>;
CsvRowParser(char separator)
: separator_(separator)
{}
RowType parse_row(std::string const& csv_row) {
std::vector<std::string> columns;
boost::algorithm::split(columns, csv_row, [this](char c) { return c == separator_; });
if(columns.size() != sizeof...(ColumnTypes))
throw std::runtime_error("Invalid csv row: " + csv_row);
return convert_csv_row(columns, std::make_index_sequence<sizeof...(ColumnTypes)>{});
}
};
int main() {
std::string my_csv;
my_csv += "abc, 1, 1.1\n";
my_csv += "def, 2, 2.2\n";
std::istringstream s(my_csv);
using Parser = CsvRowParser<std::string, int, double>;
Parser parser(',');
std::vector<Parser::RowType> rows;
for(std::string line; getline(s, line);)
rows.push_back(parser.parse_row(line));
}
I am trying to write a program hat removes the character 'p' in Pineapple to output the word Pineale. Here is my current code. I found similar problems to this and thought this code would work but it is not unfortunately. Any help is appreciated!
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <limits>
using namespace std;
int main(){
remove(c,s);
}
string remove(char c, const string & s){
string s = "Pineapple";
char chars[] = "p";
for (unsigned int i = 0; i < strlen(chars); ++i)
{
s.erase(remove(s.begin(), s.end(), chars[i]), s.end());
}
cout << s << endl;
return s;
}
First, you did not define any c or s variables.
Second, your parameter in remove function is const, that means s is unchangeable.
The code below works in my VS2013.
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <limits>
using namespace std;
string remove(char* charToRemove, string &str){
//string s = "Pineapple";
//char chars[] = "p";
for (unsigned int i = 0; i < strlen(charToRemove); ++i)
{
str.erase(remove(str.begin(), str.end(), charToRemove[i]), str.end());
}
cout << str << endl;
return str;
}
int _tmain(int argc, _TCHAR* argv[])
{
string str("Pineapple");
char chars[] = "p";
remove(chars, str);
int i;
cin >>i;
}
Simply get the position of first 'p' from "Pineapple" using string::find(), then use string::erase(). No need to put string::erase() inside the loop.
string remove(char to_rem, string s) {
size_t pos = s.find( to_rem );
s.erase(pos, count(s.begin(), s.end(), to_rem) );
return s;
}
Modified code:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
string remove(char to_rem, string s) {
size_t pos = s.find( to_rem );
s.erase(pos, count(s.begin(), s.end(), to_rem) );
return s;
}
int main() {
cout << remove('p', "Pineapple");
}
Output:
Pineale
Try this:
struct slash_pred
{
char last_char;
slash_pred()
: last_char( '\0' ) // or whatever as long as it's not '/'
{
}
bool operator()(char ch)
{
bool remove = (ch == '/') && (last_char == '/');
last_char = ch;
}
};
path.erase( std::remove_if( path.begin(), path.end(),
slash_pred() ), path.end() );
I have a file that has strings such as
Hello my name is Joe
How are you doing?
Good you?
I'm trying to output that file as it is, but my program is outputting it as "HellomynameisJoeHowAreyouDoing?Goodyou?" I'm having problems with spaces and new lines.
int main (int argc, char* argv[])
{
index_table table1;
string word;
ifstream fileo;
fileo.open(argv[1]); //where this is the name of the file that is opened
vector<string> line;
while (fileo >> word){
line.push_back(word);
}
cout << word_table << endl;
for (int i=0; i < line.size(); i++)
{
if (find(line.begin(), line.end(), "\n") !=line.end())
cout << "ERRROR\n"; //My attempt at getting rid of new lines. Not working though.
cout << line[i];
}
fileo.close();
return 0;
Just use: std::getline
while (std::getline(fileo, word))
{
line.push_back(word);
}
And then,
for (int i=0; i < line.size(); i++)
{
std::cout<<line[i]<<std::endl;
}
OR simply:-
std::copy(line.begin(), line.end(),
std::ostream_iterator<std::string>(std::cout, "\n") );
//With C++11
for(const auto &l:line)
std::cout<<l<<std::endl;
An alternate solution (with no custom loops):
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
struct line_reader : std::ctype<char>
{
line_reader() : std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
rc['\n'] = std::ctype_base::space;
rc[' '] = std::ctype_base::alpha;
return &rc[0];
}
};
int main()
{
std::ifstream fin("input.txt");
std::vector<std::string> lines;
fin.imbue(std::locale(std::locale(), new line_reader())); // note that locale will try to delete this in the VS implementation
std::copy(std::istream_iterator<std::string>(fin), std::istream_iterator<std::string>(), std::back_inserter(lines));
// file contents now read into lines
fin.close();
// display in console
std::copy(lines.begin(), lines.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
If I have the string "2.5 4.2 6.9 1.1", how can I convert that into a vector of doubles as efficiently as possible?
vector<double> convert_string_to_vec(std::string const & str)
{
std::istringstream input{str};
vector<double> output{std::istream_iterator<double>{input},
std::istream_iterator<double>{}};
return output;
}
You'll need to include <sstream> as well as <iterator> for this to work. Here's a working example.
This is how I would generally do it. Possibly not the most efficient way, but very simple.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
std::string d("2.5 4.2 6.9 1.1");
std::stringstream s(d);
std::vector<double> result;
double temp;
while(s >> temp)
{
result.push_back(temp);
}
for(size_t i = 0; i < result.size(); ++i)
{
std::cout << result[i] << "\n";
}
return 0;
}
Here's a unique way:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
template <class Facet>
struct erasable_facet : Facet
{
erasable_facet() : Facet(0) { }
~erasable_facet() { }
};
std::vector<double> convert(const std::string& str)
{
using num_get = std::num_get<char>;
erasable_facet<num_get> facet;
std::stringbuf buf(str);
std::vector<double> v;
std::ios ios(nullptr);
std::ios_base::iostate err = std::ios_base::goodbit;
double d;
std::istreambuf_iterator<char> it, end;
do
{
it = facet.get(&buf, end, ios, err, d);
buf.sbumpc(); // skip space
if (!(err & std::ios_base::failbit) &&
!(err & std::ios_base::badbit))
v.push_back(d);
else
return v;
} while (it != end);
return v;
}
int main()
{
std::string str = "1.24 5.32 9.53";
auto v = convert(str);
}
I have a vector of strings. Need help figuring out how to convert it into vector of integers in order to be able to work with it arithmetically. Thanks!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
//HELP NEEDED HERE
//CONVERSION CODE from vector<string> to vector<int>
int sum;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
There are mulitple ways of converting a string to an int.
Solution 1: Using Legacy C functionality
int main()
{
//char hello[5];
//hello = "12345"; --->This wont compile
char hello[] = "12345";
Printf("My number is: %d", atoi(hello));
return 0;
}
Solution 2: Using lexical_cast(Most Appropriate & simplest)
int x = boost::lexical_cast<int>("12345");
Surround by try-catch to catch exceptions.
Solution 3: Using C++ Streams
std::string hello("123");
std::stringstream str(hello);
int x;
str >> x;
if (!str)
{
// The conversion failed.
}
Use boost::lexical_cast. And surround it with try-catch block.
try
{
for (size_t i=0; i<vectorOfStrings.size(); i++)
{
vectorOfIntegers.push_back(boost::lexical_cast<int>(vectorOfStrings[i]));
}
}
catch(const boost::bad_lexical_cast &)
{
//not an integer
}
Or you can use Boost.Spirit parser (which someone claims is faster than even atoi()) as:
int get_int(const std::string & s)
{
int value = 0;
std::string::const_iterator first = s.begin();
bool r = phrase_parse(first,s.end(),*int_[ref(value)=_1], space);
if ( !r || first != s.end()) throw "error";
return value;
}
//Usage
int value = get_int("17823");
std::cout << value << std::endl; //prints 17823
The full demo using your code : http://ideone.com/DddL7
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/lexical_cast.hpp>
using namespace std;
int stringToInteger(const std::string& s)
{
return boost::lexical_cast<int>(s);
}
int main(int /*argc*/, char* /*argv*/[])
{
vector<string> vectorOfStrings;
// ..
vector<int> vectorOfIntegers;
std::transform(vectorOfStrings.begin(), vectorOfStrings.end(), std::back_inserter(vectorOfIntegers), stringToInteger);
// ..
}
You can replace the implementation of stringToInteger(..) with your preferred conversion function.
Here is the working version made up using the above comments.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
int x;
for (int i=0; i<vectorOfStrings.size(); i++)
{
stringstream str(vectorOfStrings.at(i));
str >> x;
vectorOfIntegers.push_back(x);
}
int sum = 0;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
What about:
#include <algorithm>
#include <boost/lexical_cast.hpp>
template<typename C1, typename C2>
void castContainer(const C1& source, C2& destination)
{
typedef typename C1::value_type source_type;
typedef typename C2::value_type destination_type;
destination.resize(source.size());
std::transform(source.begin(), source.end(), destination.begin(), boost::lexical_cast<destination_type, source_type>);
}
It can convert vector<string> into vector<int>, and also other container<T1> into container2<T2>, e.g.: list -> list.
Full code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <boost/lexical_cast.hpp>
template<typename C1, typename C2>
void castContainer(const C1& source, C2& destination)
{
typedef typename C1::value_type source_type;
typedef typename C2::value_type destination_type;
destination.resize(source.size());
std::transform(source.begin(), source.end(), destination.begin(), boost::lexical_cast<destination_type, source_type>);
}
template<typename T, typename T2>
std::vector<T>& operator<<(std::vector<T>& v, T2 t)
{
v.push_back(T(t));
return v;
}
main(int argc, char *argv[])
{
std::vector<std::string> v1;
v1 << "11" << "22" << "33" << "44";
std::cout << "vector<string>: ";
std::copy(v1.begin(), v1.end(), std::ostream_iterator<std::string>(std::cout, ", "));
std::cout << std::endl;
std::vector<int> v2;
castContainer(v1, v2);
std::cout << "vector<int>: ";
std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
}
There are two independent tasks.
Convert a single string to an integer
Having something that can convert from A to B, convert std::vector<A> to std::vector<B>
I suggest you try to do them separately, and then combine the results. If one of these tasks proves difficult, you will be able to ask a more focused question.
The most general way to convert strings to integers is with stringstream and a function template. You can optionally set the base for the conversion if you're dealing with hexadecimal. The boost library would also be helpful in your example.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <boost/static_assert.hpp>
#include <boost/foreach.hpp>
/******************************************************************************
* Handy string to type conversion
* First parameter is the string to convert
* Second optional parameter is the number base, e.g. std::hex
*
* Because this is a function template, the compiler will instantiate one
* instance of the function per type
*****************************************************************************/
// the std::dec thingy is actually a function, so extra glue required.
typedef std::ios_base& (*ios_base_fn)( std::ios_base& str );
template <class T>
T strtotype( const std::string& s, ios_base_fn base = std::dec )
{
// C++ can't convert 8-bit values, they are *always* treated
// as characters. :( At least warn the user.
// this gives a cryptic error message, but better than nothing.
BOOST_STATIC_ASSERT( sizeof(T) > 1 );
T val;
std::istringstream iss(s);
iss >> base >> val;
if( iss.fail() )
throw std::runtime_error( "Error: strtotype(): Can't convert string '" + s + "' to numeric value" );
return val;
}
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
for( size_t i = 0; i < vectorOfStrings.size(); i++ )
vectorOfIntegers.push_back( strtotype<int>( vectorOfStrings[i] ));
// or better yet, use boost_foreach
BOOST_FOREACH( const string& s, vectorOfStrings )
vectorOfIntegers.push_back( strtotype<int>( s ));
int sum;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
If you don't want or can't use boost, you can remove the sizeof() check in strtotype. However, be careful never to try to convert to strings to individual bytes. Doing so will fail silently by only converting the first nibble of the byte.
If you're suing GNU tools, then compile like so:
g++ -Wall -O3 -I /path/to/boost/include main.cpp
or, if you delete the boost related bits:
g++ -Wall -O3 main.cpp