Is there any way that I can use istringstream to read strings with embedded null characters? For example, if I have a char array "125 320 512 750 333\0 xyz". Is there any way that I could get "xyz" after the null character?
#include <iostream>
#include <sstream>
using namespace std;
int main() {
std::string stringvalues = "125 320 512 750 333\0 xyz";
cout << "val: " << stringvalues << endl;
std::istringstream iss (stringvalues);
for (int n=0; n<10; n++)
{
string val;
iss >> val;
std::cout << val << '\n';
}
return 0;
}
This is an example modified from cplusplus.com. I want to get the part after the null character, and I am curious whether I can get it without knowing the exact length of the char array. Thanks in advance.
Just properly initialize string with the proper size of the char array. The rest will follow naturally.
#include <sstream>
#include <string>
#include <cstring>
#include <iostream>
#include <iomanip>
int main() {
const char array[] = "125 320 512 750 333\0 xyz";
// to get the string after the null, just add strlen
const char *after_the_null_character = array + strlen(array) + 1;
std::cout << "after_the_null_character:" << after_the_null_character << std::endl;
// initialized with array and proper, actual size of the array
std::string str{array, sizeof(array) - 1};
std::istringstream ss{str};
std::string word;
while (ss >> word) {
std::cout << "size:" << word.size() << ": " << word.c_str() << " hex:";
for (auto&& i : word) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned)i;
}
std::cout << "\n";
}
}
would output:
after_the_null_character: xyz
size:3: 125 hex:313235
size:3: 320 hex:333230
size:3: 512 hex:353132
size:3: 750 hex:373530
size:4: 333 hex:33333300
size:3: xyz hex:78797a
Note the zero byte after reading 333.
Is there any way that I can use istringstream to read strings with embedded null characters?
Yes. You can use any of the UnformattedInputFunctions such as the read member function to read input including null chars.
Note however that your stringvalues does not contain anything after the null char and thus neither does the string stream constructed from it. If you want a std::string that contains null chars (other than the terminating one), then you can use for example the constructor that accepts a size as second argument.
I want to get the part after the null character, and I am curious whether I can get it without knowing the exact length of the char array.
Here is a simple way:
const char* string = "125 320 512 750 333\0 xyz";
std::size_t length = std::strlen(string);
const char* xyz = string + length + 1;
Related
While working on a project, I found myself wondering how to convert from string to hex. Not just converting from, let's say, the string "42" to hex 0x3432.
I'm curious how you would go about converting the string "0x42" to hex 0x42. As in, assume the string given is a valid hex number (I know that's a big assumption, but go with it...). I want to use that as a hex number, not as a string anymore. How would I go about doing that conversion?
This isn't something I'd do... I'm just more curious if and how it would be done, as I've never run into this type of problem until now.
*Using C and C++
As this is just a matter of different representations of the same value, its IO streams that offer such "conversion":
#include <sstream>
#include <iostream>
int main() {
std::stringstream ss{"0x42"};
int x = 0;
ss >> std::hex >> x;
std::cout << x << "\n";
std::cout << std::hex << x;
}
Output:
66
42
Like this:
#include <string>
#include <iostream>
int main()
{
std::string s = "0x42";
int i = std::stoi( s, nullptr, 16 );
int j = strtoul( s.substr(2).c_str(), nullptr, 16 );
std::cout << i << "," << j << "\n";
}
Note that std::stoi will handle the leading "0x". strtoul is pickier.
I am trying to read a txt file and store the content as variables. But the problem is that the txt file can have different contents. like for example,
txt1:
2 5000
P 900 15 200 L(1) 300 U(1) 400
A 2 10 500
txt2:
4 5000
P 350 81 10 L(1) 90 U(1) 300
P 500 50 100 L(5) 90 L(4) 90 L(3) 90 U(3) 90 U(4) 10 U(5) 100
A 1 90 500
A 7 93 50 L(1) 100 U(1) 300
So i have written a code that considers the following assumption,
line starting with 'A' has 3 parameters and with 'P' has 7 as in example 1. I do not know how to convert it to be generic.
The code is
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
struct specs
{
int ttime,priority,iter1,iter_lock,iter_unlock,event;
char lock_num[4];
char unlock_num[4];
char unlockid,lockid;
}obj[100];
int main()
{
int i,j,k;
int num_thread,time;
char t[200];
ifstream in("data.txt");
if ( !in )
{
cout << "Error: Can't open the file named data.txt.\n";
exit(1);
}
in >> num_thread;
in >> time;
cout << "Number of threads = "<< num_thread << endl ;
cout << "Total time is = " << time << endl;
for (k = 0; k < num_thread;k++)
{
in >> t[k];
if (t[k] == 'A')
{
in >> obj[k].event;
in >> obj[k].priority;
in >> obj[k].iter1;
cout << obj[k].iter1<<endl;
}
else if (t[k] == 'P' )
{
in >> obj[k].ttime;
in >> obj[k].priority;
in >> obj[k].iter1;
in >> obj[k].lock_num;
in >> obj[k].iter_lock;
in >> obj[k].unlock_num;
in >> obj[k].iter_unlock;
cout << obj[k].unlock_num<<endl;
cout << obj[k].iter_lock<<endl;
obj[k].unlockid = obj[k].unlock_num[2];
obj[k].lockid = obj[k].lock_num[2];
cout<< obj[k].unlockid <<endl;
cout<< obj[k].lockid <<endl;
int xx = obj[k].unlockid - '0';
cout << xx<<endl;
}
else cout << " Invalid parameter";
}
in.close();
return 0;
}
There are a number of ways to do this, each with varying levels of complexity depending on what you want to do with the data.
Given the constraints of your data, I assume that at some point you wish to parse the numeric items into numbers and the string items into strings.
However, as your input isn't fixed and the type (string or int) vary in ordering, this is potentially problematic.
One way is to use the whitespace to your advantage and tokenize the data into strings, then parse the tokens to determine if they are strings or numbers, and store them accordingly in their own separate containers.
To that end, I've done the first part of breaking the file and lines into tokens and storing and outputting them in the following:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstdlib>
#include <sstream>
using namespace std;
int main() {
string filename = "txt1.txt";
string temp;//a temporary variable used to store string data
vector < vector <string> > tokens;
vector < vector <string> >::iterator it;//used to iterate over `tokens`
//used to iterate over the individual elements of `token`
vector <string>::iterator jt;
//initialize the `ifstream` object with the filename
ifstream ifile(filename.c_str());
//check to see if the file opened correctly
if (ifile.is_open()) {
//the file has been opened, now operate on it
//by parsing over it and breaking each constituent line
//into tokens:
while(getline(ifile, temp)) {
//initialize the string stream with the line that
//was stored with getline:
istringstream iss(temp);
//this is a temporary vector to store the tokens per line
vector <string> tokens_in_line;
//use the whitespace to your advantage by using the
//extraction operator to parse over the tokens
//in each line and store them in the temporary vector (above)
while(iss >> temp) {
tokens_in_line.push_back(temp);
}
//at this point we may or may not have data in the temporary
//vector. Check to see if its empty, if so reject storing it
if (!tokens_in_line.empty()) {
tokens.push_back(tokens_in_line);
}
}
}
else {
cerr << "There was an error opening the input file!" << endl;
exit(1);
}
ifile.close();
//now output the information:
for (it = tokens.begin(); it != tokens.end(); ++it) {
for (jt = it->begin(); jt != it->end(); ++jt) {
cout << *jt << " ";
}
cout << endl;
}
return 0;
}
All you have to do at this point is figure out how to store the data for the strings and numbers in their own separate containers for later access. While that may seem daunting, if you follow my comments, it should be easy to figure out what to do and where to do it.
UPDATE:
Regarding parsing the string tokens for the integer numbers, you can do something like this for those tokens (I've implemented it this way, as it's possible that the integer can be greater than a single digit):
std::string numbers = "0123456789";
std::string token = "L(1)";
std::size_t begin = token.find_first_of(numbers.c_str());
std::size_t end = token.find_last_of(numbers.c_str());
std::string num_str = input2.substr(begin, end-1);
std::cout << num_str << std::endl;
All you have to do at this point is convert the num_str value to an integer. There's one caveat to this though: it assumes that the numbers are contiguous and occur only once - otherwise, you'll have problems.
I want to ask for word from the user and then convert the word from string to char using 'strcpy'. Then I want to determine the sum of the ascii codes for all of the letters in the word.
However, I am having difficulties. I don't understand exactly how I can do that. This is what I have been able to do so far.
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
string word;
cout << "Enter word: ";
getline(cin, word);
/*
char w[word];
strcpy(w,word.c_str());
int ('A');
cout<<char(65);
*/
return 0;
}
The commented part is where I have been trying to do the converting. I copied the code from a worksheet. Even if it did work, I don't know how, and what it all means.
Thanks for your help.
char w[word];
strcpy(w, word.c_str());
char w[word] is incorrect. The square brackets is for the size, which must be a constant integral expression. word is of type std::string, so this makes neither logical nor practical sense. Maybe you meant it as:
char w = word;
But that still won't work because word is a string, not a character. The correct code in this case is:
char* w = new char[word.size() + 1];
That is, you allocate the memory for w using a char*. Then you use word.size() + 1 to initialize heap-allocated memory amounting to those bytes. Don't forget for the obligatory delete[] when you're finished using w:
delete[] w;
However, note that using raw pointers and explicit new is not needed in this case. Your code can easily be cleaned up into the following:
#include <numeric>
int main ()
{
std::string word;
std::getline(std::cin, word);
int sum = std::accumulate(word.begin(), word.end(), 0); /*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
std::cout << "The sum is: " << sum << std::endl;
}
You don't need to use strcpy() (or use a char * at all, for that matter), but this'll do your counting using a char pointer:
#include <iostream>
#include <string>
int main() {
std::string word;
std::cout << "Enter word: ";
std::cin >> word;
const char * cword = word.c_str();
int ascii_total = 0;
while ( *cword ) {
ascii_total += *cword++;
}
std::cout << "Sum of ASCII values of characters is: ";
std::cout << ascii_total << std::endl;
return 0;
}
Output:
paul#local:~/src/cpp/scratch$ ./asccount
Enter word: ABC
Sum of ASCII values of characters is: 198
paul#local:~/src/cpp/scratch$
If you really do want to use strcpy(), I'll leave it as an exercise to you to modify the above code.
Here's a better way to do it, just using std::string (and C++11, and obviously presuming your system uses the ASCII character set in the first place):
#include <iostream>
#include <string>
int main() {
std::string word;
std::cout << "Enter word: ";
std::cin >> word;
int ascii_total = 0;
for ( auto s : word ) {
ascii_total += s;
}
std::cout << "Sum of ASCII values of characters is: ";
std::cout << ascii_total << std::endl;
return 0;
}
This question already has answers here:
How do I iterate over the words of a string?
(84 answers)
Closed 9 years ago.
I am having problems splitting a string using pure C++
The string always looks like this
12344//1238
First int then // and then the second int.
Need help to get the two int values and ignore the //
string org = "12344//1238";
size_t p = org.find("//");
string str2 = org.substr(0,p);
string str3 = org.substr(p+2,org.size());
cout << str2 << " "<< str3;
why cant we use sscanf?
char os[20]={"12344//1238"};
int a,b;
sscanf(os,"%d//%d",a,b);
Reference
Take a look at the strtok function
This should Split and convert to integers:
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
inline double convertToInt(std::string const& s,
bool failIfLeftoverChars = true)
{
std::istringstream i(s);
int x;
char c;
if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
throw BadConversion("convertToInt(\"" + s + "\")");
return x;
}
int main()
{
std::string pieces = "12344//1238";
unsigned pos;
pos = pieces.find("//");
std::string first = pieces.substr(0, pos);
std::string second = pieces.substr(pos + 2);
std::cout << "first: " << first << " second " << second << std::endl;
double d1 = convertToInt(first), d2 = convertToInt(second) ;
std::cout << d1 << " " << d2 << std::endl ;
}
Simplest way I can think of:
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
void main ()
{
int int1, int2;
char slash1, slash2;
//HERE IT IS:
stringstream os ("12344//1238");
os>> int1 >> slash1 >> slash2 >> int2;
//You may want to verify that slash1 and slash2 really are /'s
cout << "I just read in " << int1 << " and " << int2 << ".\n";
system ("pause");
}
Also nice because it's so easy to rewrite -- if, say, you decide to read in ints delimited by something else.
Take the integers in as a string.
The string will then have the numbers and the // symbols.
Next you can run a simple for loop looking for the '/' in the string.
The values prior to the symbol are stored in another string.
When '/' appears, the for loop will terminate. You now have the index of the first
'/' symbol.
Increment the index and copy the rest of the string using anothe for loop, in another
string.
Now you have two separate strings.
How do I get a part of a string in C++? I want to know what are the elements from 0 to i.
You want to use std::string::substr. Here's an example, shamelessly copied from http://www.cplusplus.com/reference/string/string/substr/
// string::substr
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str="We think in generalities, but we live in details.";
// quoting Alfred N. Whitehead
string str2, str3;
size_t pos;
str2 = str.substr (12,12); // "generalities"
pos = str.find("live"); // position of "live" in str
str3 = str.substr (pos); // get from "live" to the end
cout << str2 << ' ' << str3 << endl;
return 0;
}
You use substr, documented here:
#include <iostream>
#include <string>
using namespace std;
int main(void) {
string a;
cout << "Enter string (5 characters or more): ";
cin >> a;
if (a.size() < 5)
cout << "Too short" << endl;
else
cout << "First 5 chars are [" << a.substr(0,5) << "]" << endl;
return 0;
}
You can also then treat it as a C-style string (non-modifiable) by using c_str, documented here.
If the string is declared as an array of characters, you can use the following approach:
char str[20];
int i;
strcpy(str, "Your String");
// Now let's get the sub-string
cin >> i;
// Do some out-of-bounds validation here if you want..
str[i + 1] = 0;
cout << str;
If you mean std::string, use substr function as Will suggested.
Assuming you're using the C++ std::string class
you can do:
std::string::size_type start = 0;
std::string::size_type length = 1; //don't use int. Use size type for portability!
std::string myStr = "hello";
std::string sub = myStr.substr(start,length);
std::cout << sub; //should print h
use:
std::string sub_of_s(s.begin(), s.begin()+i);
which create a string sub_of_s which is the first i-th the element in s.