SScanf for CString not working? - c++

I just want to split this string by the char ":"
for example "first:last"
so one string will have "first" and the other will have "last"
I did like the one in this url (sscanf string splitting not working)
but it didn't work well with me as both strings will have the "last" value
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <cstring>
#include<tchar.h>
#include<atlstr.h>
using namespace std;
void main()
{
CString firstString(""), secondString(""), myString("first:last");
sscanf(myString, "%[^:]:%s", firstString, secondString);
printf("first: %s, last: %s", firstString, secondString);
system("pause");
}

As mentioned above, do not mix C "strings" and MFC CStrings. Here's a solution using MFC CString:
const int iColon = myString.Find(':');
if (iColon >= 0)
{
firstString = myString.Left(iColon);
secondString = myString.Mid(iColon+1);
}

Related

Managing Strings In C++

So I make an array of string pointers and put a string in at position 0 of the array. If I don't know the length of the string in word[0] how do I find it? How do I then manage that string, because I want to remove the "_." and "." part of the string so I will be left with "apple Tree".How do I resize that string? (functions like strcpy,strlen, or string.end() didn't work, I get errors like "can't convert string to char*" etc)
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string>
using namespace std;
int main()
{
int counter=0;
string* word = new string[0];
word[0] = "apple_.Tree.";
return 0;
}
Edit:what i want to do is make a dynamic array of strings(not using vector) and then edit the strings inside
string is a class, so you can use its member functions to manage it. See the documentation.
To remove characters, use std::erase (see this answer).
#include <iostream>
#include <string>
#include <algorithm>
int main() {
// Create array of 10 strings
std::string array[10];
array[0] = "apple_.Tree.";
std::cout << array[0].size() << "\n";
array[0].erase(std::remove(array[0].begin(), array[0].end(), '.'), array[0].end());
array[0].erase(std::remove(array[0].begin(), array[0].end(), '_'), array[0].end());
std::cout << array[0];
return 0;
}

Is there a quick way to check if a string is numeric?

Is it possible to check if a string variable is entirely numeric? I know you can iterate through the alphabets to check for a non-numeric character, but is there any other way?
The quickest way i can think of is to try to cast it with "strtol" or similar functions and see whether it can convert the entire string:
char* numberString = "100";
char* endptr;
long number = strtol(numberString, &endptr, 10);
if (*endptr) {
// Cast failed
} else {
// Cast succeeded
}
This topic is also discussed in this thread: How to determine if a string is a number with C++?
Hope this helps :)
#include <iostream>
#include <string>
#include <locale>
#include <algorithm>
bool is_numeric(std::string str, std::locale loc = std::locale())
{
return std::all_of(str.begin(), str.end(), std::isdigit);
}
int main()
{
std::string str;
std::cin >> str;
std::cout << std::boolalpha << is_numeric(str); // true
}
You can use the isdigit function in the ctype library:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main ()
{
char mystr[]="56203";
int the_number;
if (isdigit(mystr[0]))
{
the_number = atoi (mystr);
printf ("The following is an integer\n",the_number);
}
return 0;
}
This example checks the first character only. If you want to check the whole string then you can use a loop, or if its a fixed length and small just combine isdigit() with &&.

Using strtok() to parse text file

I've been trying to make a program that parses a text file and feeds 6 pieces of information into an array of objects. The problem for me is that I'm having issues figuring out how to process the text file. I was told that the first step I needed to do was to write some code that counted how many letters long each entry was. The txt file is in this format:
"thing1","thing2","thing3","thing4","thing5","thing6"
This is the current version of my code:
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
int main()
{
ifstream myFile("Book List.txt");
while(myFile.good())
{
string line;
getline(myFile, line);
char *sArr = new char[line.length() + 1];
strcpy(sArr, line.c_str());
char *sPtr;
sPtr = strtok(sArr, " ");
while(sPtr != NULL)
{
cout << strlen(sPtr) << " ";
sPtr = strtok(NULL, " ");
}
cout << endl;
}
myFile.close();
return 0;
}
So there are two things making it hard for me right now.
1) How do I deal with the delimiters?
2) How do I deal with "skipping" the first quotation mark in each line?
Read in a string instead of a c-style string. This means that you can use the handy std methods.
The std::string::find() method should help you out with finding each thing that you want to parse.
http://www.cplusplus.com/reference/string/string/find/
You can use this to find all the commas, which will give you the starts of all the things.
Then you can use std::string::substr() to cut up the string into each piece.
http://www.cplusplus.com/reference/string/string/substr/
You can manage to get rid of the quotation marks by passing in 1 more than the start and 1 less than the length of the thing, you can also use
If you have to use strtok then this code snippet should give enough to modify your program to parse your data:
#include <cstdio>
#include <cstring>
int main ()
{
char str[] ="\"thing1\",\"thing2\",\"thing3\",\"thing4\",\"thing5\"";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,"\",");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, ",\"");
}
return 0;
}
If you do not have to use strtok then you should use std::string as others have advised. Using std::string and std::istringstream:
#include <string>
#include <sstream>
#include <vector>
#include <iostream>
int main ()
{
std::string str2( "\"thing1\",\"thing2\",\"thing3\",\"thing4\",\"thing5\"" ) ;
std::istringstream is(str2);
std::string part;
while (getline(is, part, ','))
std::cout << part.substr(1,part.length()-2) << std::endl;
return 0;
}
For starters, don't use strtok if you can avoid it (and you easily can here - and you can even avoid using the find series of functions as well).
If you want to read in the whole line and then parse it:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
// defines a new ctype that treats commas as whitespace
struct csv_reader : std::ctype<char>
{
csv_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::space;
return &rc[0];
}
};
int main()
{
std::ifstream fin("yourFile.txt");
std::string line;
csv_reader csv;
std::vector<std::vector<std::string>> values;
while (std::getline(fin, line))
{
istringstream iss(line);
iss.imbue(std::locale(std::locale(), csv));
std::vector<std::string> vec;
std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter(vec));
values.push_back(vec);
}
// values now contains a vector for each line that has the strings split by their commas
fin.close();
return 0;
}
That answers your first question. For your second, you can skip all the quotation marks by adding them to the rc mask (also treating them as whitespace) or you can strip them out afterwards (either directly or by using a transform):
std::transform(vec.begin(), vec.end(), vec.begin(), [](std::string& s)
{
std::string::iterator pend = std::remove_if(s.begin(), s.end(), [](char c)
{
return c == '"';
});
s.erase(pend, s.end());
});

Getting string input with a default value supplied in C++

I want to get string input from the user. At the same time, I want to supply a default string so that if the user doesn't want to change it, they can just press enter. How can that be done in C++?
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* args[])
{
const string defaultText = "Default string";
string str;
string tmp;
getline(cin, tmp);
if (!tmp.empty()) //user typed something different than Enter
str = tmp;
else //otherwise use default value
str = defaultText;
cout << str << endl;
}
You should be able to do it with the version of getline() defined in . You can use it like this:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
getline(cin,str);
// Use str
}
Just use two strings: Default string and User_supplied string. Get the input from the user (for the user_supplied string) and do an strlen on this string to check if it has a length greater than zero. If so use the User_supplied string, else use the default string

"printf" on strings prints gibberish

I'm trying to print a string the following way:
int main(){
string s("bla");
printf("%s \n", s);
.......
}
but all I get is this random gibberish.
Can you please explain why?
Because %s indicates a char*, not a std::string. Use s.c_str() or better still use, iostreams:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("bla");
std::cout << s << "\n";
}
You need to use c_str to get c-string equivalent to the string content as printf does not know how to print a string object.
string s("bla");
printf("%s \n", s.c_str());
Instead you can just do:
string s("bla");
std::cout<<s;
I've managed to print the string using "cout" when I switched from :
#include <string.h>
to
#include <string>
I wish I would understand why it matters...
Why don't you just use
char s[]="bla";