garbage character at end of string? - c++

Hi there I'm reading a string and breaking each word and sorting it into name email and phone number. with the string joe bloggs joeblog#live.com 12345. But once i break everything down, the individual separated variables which hold the name,email and phone number have garbage characters at the end of them. I cant figure out why.
test file
//test file
#include <iostream>
#include <string>
#include "iofunc.h"
using namespace std;
int main(){
string str1 = "joe bloggs joeblog#live.com 12345";
iofunc func;
cout<<"|-----------------------getname DEMONSTRATION------------------|\n" << endl;
func.getName(str1);
cout<<"the names are: " << func.glob_name << endl;
cout<<"\n|-----------------------getphone DEMONSTRATION------------------|\n" << endl;
func.getPhone(str1);
cout<<"the phone number is:" << func.glob_phone << endl;
cout<<"\n|-----------------------getemail DEMONSTRATION------------------|\n" << endl;
func.getEmail(str1);
cout<<"the email address is:" << func.glob_email << endl;
return 0;
}
here's my get name function, the class is too big to scroll through:)
void iofunc::getName(string arg){
lineProcess(arg);
//make sure to call this depending on what function u are using
int name_count = 0;
int wspace_count = 0;
int arg_len = arg.length();
//int char_len = 0;
char name_temp[80];
name_count = numberofNames();
//line process was called before so this will work,
//make sure you call line process before using this function
//for special, condition when there is no space in front of names
if (special_condition == true){
int i = 0;
while(i < arg_len){
name_temp[i] = arg[i];
i++;
}
glob_name = string(name_temp);
}
if (special_condition == false){
if (name_count == 1){
int i = 0;
while (arg[i] != ' '){
name_temp[i] = arg[i];
i++;
}
glob_name = string(name_temp);
}
//for 2 names
if (name_count == 2){
for (int i = 0; i < arg_len;i++){
if (arg[i] == ' '){
wspace_count++;
}
if (wspace_count !=2){
name_temp[i] = arg[i];
}
}
glob_name = string(name_temp);
}
//for 3 names
if (name_count == 3){
for (int i = 0; i < arg_len;i++){
if (arg[i] == ' '){
wspace_count++;
}
if (wspace_count !=3){
name_temp[i] = arg[i];
}
}
glob_name = string(name_temp);
}
}
}
basic jist of all that is, im using the function called lineProcess to figure out whether there is an email, phone and name in the argument string, And the numberofNames functions gives how many names there are so that I can act accordingly.
I had to use char name_temp to copy just the names from string so that I can extract just that and assign it to the string variable named glob_name. It copies everything i need but it gives me that garbage after each extracted string.
any idea?.
EDITED
void iofunc::getName(string arg){
lineProcess(arg);
//make sure to call this depending on what function u are using
int name_count = 0;
int wspace_count = 0;
int arg_len = arg.length();
//int char_len = 0;
char name_temp[80];
int index_track = 0;
name_count = numberofNames();
//line process was called before so this will work,
//make sure you call line process before using this function
//for special, condition when there is no space in front of names
if (special_condition == true){
int i = 0;
while(i < arg_len){
name_temp[i] = arg[i];
index_track = i;
i++;
}
name_temp[index_track+1] = '\0';
glob_name = string(name_temp);
}
if (special_condition == false){
if (name_count == 1){
int i = 0;
while (arg[i] != ' '){
name_temp[i] = arg[i];
index_track = i;
i++;
}
name_temp[index_track+1] = '\0';
glob_name = string(name_temp);
}
//for 2 names
if (name_count == 2){
for (int i = 0; i < arg_len;i++){
if (arg[i] == ' '){
wspace_count++;
}
if (wspace_count !=2){
name_temp[i] = arg[i];
index_track = i;
}
}
name_temp[index_track+1] = '\0';
glob_name = string(name_temp);
}
//for 3 names
if (name_count == 3){
for (int i = 0; i < arg_len;i++){
if (arg[i] == ' '){
wspace_count++;
}
if (wspace_count !=3){
name_temp[i] = arg[i];
index_track = i;
}
}
name_temp[index_track+1] = '\0';
glob_name = string(name_temp);
}
}
}

When you do things like this:
while(i < arg_len){
name_temp[i] = arg[i];
i++;
}
You are copying the characters of the string to name_tmp, but not the 0 at the end which terminates the string.

add to each new string '\0' end-of string symbol

Garbage characters at the end of a string could indicate that you're not null-terminating the string (ending it with a 0x00 byte). This causes the string to continue reading until the next null character, which is actually past where the string's memory ends. This could even cause a segmentation fault in some cases.
You can fix this by adding '\0' to the end of each new string you create. Note that you will have to allocate a string one byte larger now, to hold that new ending character.

The others have pointed you in the right direction, you aren't appropriately terminating your c strings. Declaring a char array of length 80 just points to a block of memory, it doesn't initialise the array in any way, this means that unless you /0 terminate the string you copy into it, you'll get all the crap lying around on the end up to the 80 characters.
I've not written C++ in probably 15 years so the code below may not even work but hopefully it'll give you some ideas for a more elegant and maintainable solution.
void iofunc::getName(string arg){
lineProcess(arg);
//make sure to call this depending on what function u are using
int name_count = 0;
int wspace_count = 0;
int arg_len = arg.length();
//int char_len = 0;
string name_temp;
// Let's assemble a c-str version if the inbound arg string
char* cstr;
cstr = new char [arg.size()+1];
strcpy (cstr, arg.c_str());
name_count = numberofNames();
//line process was called before so this will work,
//make sure you call line process before using this function
//for special, condition when there is no space in front of names
if (special_condition == true){
glob_name = arg;
}
if (special_condition == false){
// Assuming there's at least 1 name, which we have to otherwise the original
// code may never set glob_name, let's use the C String function strtok
// to tokenise our newly created c string at each " ".
// Grab the first name.
name_temp = string(strtok(cstr, " "));
for (int i = 1; i < name_count; i++) {
// Grab names 2 to name_count as required and append them to name_temp
// We need to reinsert the space as strtok doesn't grab it.
name_temp += " " + string(strtok(NULL, " "));
}
// Assign our final name to glob_name
glob_name = name_temp;
}
}

Related

Connecting n pipes linux

I was studying about pipes recently and saw this answer:
Connecting n commands with pipes in a shell?
I was intrigued about it and tried to make like a "dynamic" one, in which I introduce a string with n process and then execute the n process (i.e ls | sort). I was trying to tokenize, save in an array, but it did not work. Here is my code of my "tokenizer":
int main()
{
char str[] = "ls | sort";
int length = (sizeof(str) / sizeof(*str))-1;
int sizeCMD = 1; //If the string has zero pipe, it means it has at least 1 process
vector<char> tempV;
for (int i = 0; i < length; i++)
{
if (str[i] == '|')
{//If the string has one |, it means it has at least 2 process.
sizeCMD++;
}
tempV.push_back(str[i]);//I was going to do something else with this, but I forgot.
//cout<<i<<" "<<tempV.at(i)<<endl;
}
int j = 0;//Current position of the cmd
string comLetter = "";//it will save every single letter in certain conditions
string comLine = "";//it will save all the characters of comLetter in certain conditions
struct command cmd[sizeCMD];
const char *ls[2];
const char *sort[2];
const char *toCChar;
for (int i = 0; i < tempV.size(); i++)
{
if (tempV.at(i) != ' ' && tempV.at(i) != '|')
{//comLetter will only save characters that are not equal to blank or |.
//cout<<tempV.at(i);
comLetter += tempV.at(i);
//cout<< comLetter <<endl;
}
if (tempV.at(i) == ' ' || i == tempV.size() - 1)
{//comLine will save everything of comLetter when it detects a blank or the very end
//cout<<comLetter<<endl;
comLine = comLetter;
comLetter = "";
}
if (tempV.at(i) == '|' || i == tempV.size() - 1)
{//cmd will save everything of comLine when it detects a | or the very end.
//cout<<j<<endl;
cout << "." << comLine << "." << endl;
//cout<<i<<endl;
//cout<<toCChar<<endl;
if(comLine == "ls"){
toCChar = comLine.c_str();
ls[0] = toCChar;
ls[1] = 0; //THIS IF
cmd[0] = {ls}; //WORKS
}
if(comLine == "sort"){
sort[0] = "sort";
sort[1] = 0; //THIS IF
cmd[1] = {sort}; //WORKS
}
/*const char *ls[2];
cout<<toCChar<<endl;
ls[0] = toCChar;
ls[1] = 0;
cout<< *ls[0] << " - "<< endl;
cmd[j] = {ls};
//cout << cmd << endl;
comLine = "";*/
j++; //The position will move by one.
}
}
return fork_pipes(sizeCMD, cmd);
}
Everything made sense to me, until I found out that const char* can't be temporal as it needs the data, so I need to create 2 const char* arrays for 2 commands. That's why I've two arrays: *sort[] and *ls[], for sort and ls.
Also, I was wondering, why these lines get "ignored":
toCChar = comLine.c_str();
ls[0] = toCChar;
I'm struggling right now, if someone could please help/guide me on how to do it, I would appreciate that.

Trimming start of Cstring without copying

I managed to get my homework to work but It shouldn't work because i have not finished it. I don't know why it does. I need help.
#include<iostream>
using namespace std;
char* trim(char* str) {
const int lenStr = strlen(str);
int characters = 0;
bool trimmableFront = false;
int firstChar;
//check if trimmableFront + location of first char
for (int i = 0; i < lenStr; i++) {
if (*(str + i) != ' ') {
if (characters == 0)
firstChar = i;
characters++;
}
if (characters == 0) {
trimmableFront = true;
}
}
//trim Front //THIS PART SHOULD BEHAVE DIFFERENTLY
if (trimmableFront) {
for (int i = 0; i < lenStr; i++) {
if((firstChar + i <= lenStr))
*(str + i) = *(str + firstChar + i);
}
}
return str;
}
int main() {
char str[] = " why does it work?";
trim(str);
cout<< str <<endl;
return 0;
}
At the end of trim(*char) function, trimmed string should have still leftovers from previous locations.
For some reason it is perfectly trimmed and works as intended printing "why does it work?" but it should print something like "why does it workt work?"
The reason why it works is because as you trim the string by shifting each character you also shift the terminating null character '\0'. As you probably know c-strings are array of characters terminated by '\0', so as you print str with cout all characters are printed until the null value is reached: that is way the leftovers are not printed.

What's wrong with my dynamic programming algorithm with memoization?

*Sorry about my poor English. If there is anything that you don't understand, please tell me so that I can give you more information that 'make sence'.
**This is first time asking question in Stackoverflow. I've searched some rules for asking questions correctly here, but there should be something I missed. I welcome all feedback.
I'm currently solving algorithm problems to improve my skill, and I'm struggling with one question for three days. This question is from https://algospot.com/judge/problem/read/RESTORE , but since this page is in KOREAN, I tried to translate it in English.
Question
If there are 'k' pieces of partial strings given, calculate shortest string that includes all partial strings.
All strings consist only lowercase alphabets.
If there are more than 1 result strings that satisfy all conditions with same length, choose any string.
Input
In the first line of input, number of test case 'C'(C<=50) is given.
For each test case, number of partial string 'k'(1<=k<=15) is given in the first line, and in next k lines partial strings are given.
Length of partial string is between 1 to 40.
Output
For each testcase, print shortest string that includes all partial strings.
Sample Input
3
3
geo
oji
jing
2
world
hello
3
abrac
cadabra
dabr
Sample Output
geojing
helloworld
cadabrac
And here is my code. My code seems to work perfect with Sample Inputs, and when I made test inputs for my own and tested, everything worked fine. But when I submit this code, they say my code is 'wrong'.
Please tell me what is wrong with my code. You don't need to tell me whole fixed code, I just need sample inputs that causes error with my code. Added code description to make my code easier to understand.
Code Description
Saved all input partial strings in vector 'stringParts'.
Saved current shortest string result in global variable 'answer'.
Used 'cache' array for memoization - to skip repeated function call.
Algorithm I designed to solve this problem is divided into two function -
restore() & eraseOverlapped().
restore() function calculates shortest string that includes all partial strings in 'stringParts'.
Result of resotre() is saved in 'answer'.
For restore(), there are three parameters - 'curString', 'selected' and 'last'.
'curString' stands for currently selected and overlapped string result.
'selected' stands for currently selected elements of 'stringParts'. Used bitmask to make my algorithm concise.
'last' stands for last selected element of 'stringParts' for making 'curString'.
eraseOverlapped() function does preprocessing - it deletes elements of 'stringParts' that can be completly included to other elements before executing restore().
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#define MAX 15
using namespace std;
int k;
string answer; // save shortest result string
vector<string> stringParts;
bool cache[MAX + 1][(1 << MAX) + 1]; //[last selected string][set of selected strings in Bitmask]
void restore(string curString, int selected=0, int last=0) {
//base case 1
if (selected == (1 << k) - 1) {
if (answer.empty() || curString.length() < answer.length())
answer = curString;
return;
}
//base case 2 - memoization
bool& ret = cache[last][selected];
if (ret != false) return;
for (int next = 0; next < k; next++) {
string checkStr = stringParts[next];
if (selected & (1 << next)) continue;
if (curString.empty())
restore(checkStr, selected + (1 << next), next + 1);
else {
int check = false;
//count max overlapping area of two strings and overlap two strings.
for (int i = (checkStr.length() > curString.length() ? curString.length() : checkStr.length())
; i > 0; i--) {
if (curString.substr(curString.size()-i, i) == checkStr.substr(0, i)) {
restore(curString + checkStr.substr(i, checkStr.length()-i), selected + (1 << next), next + 1);
check = true;
break;
}
}
if (!check) { // if there aren't any overlapping area
restore(curString + checkStr, selected + (1 << next), next + 1);
}
}
}
ret = true;
}
//check if there are strings that can be completely included by other strings, and delete that string.
void eraseOverlapped() {
//arranging string vector in ascending order of string length
int vectorLen = stringParts.size();
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].length() < stringParts[j].length()) {
string temp = stringParts[i];
stringParts[i] = stringParts[j];
stringParts[j] = temp;
}
}
}
//deleting included strings
vector<string>::iterator iter;
for (int i = 0; i < vectorLen-1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].find(stringParts[j]) != string::npos) {
iter = stringParts.begin() + j;
stringParts.erase(iter);
j--;
vectorLen--;
}
}
}
}
int main(void) {
int C;
cin >> C; // testcase
for (int testCase = 0; testCase < C; testCase++) {
cin >> k; // number of partial strings
memset(cache, false, sizeof(cache)); // initializing cache to false
string inputStr;
for (int i = 0; i < k; i++) {
cin >> inputStr;
stringParts.push_back(inputStr);
}
eraseOverlapped();
k = stringParts.size();
restore("");
cout << answer << endl;
answer.clear();
stringParts.clear();
}
}
After determining which string-parts can be removed from the list since they are contained in other string-parts, one way to model this problem might be as the "taxicab ripoff problem" problem (or Max TSP), where each potential length reduction by overlap is given a positive weight. Considering that the input size in the question is very small, it seems likely that they expect a near brute-force solution, with possibly some heuristic and backtracking or other form of memoization.
Thanks Everyone who tried to help me solve this problem. I actually solved this problem with few changes on my previous algorithm. These are main changes.
In my previous algorithm I saved result of restore() in global variable 'answer' since restore() didn't return anything, but in new algorithm since restore() returns mid-process answer string I no longer need to use 'answer'.
Used string type cache instead of bool type cache. I found out using bool cache for memoization in this algorithm was useless.
Deleted 'curString' parameter from restore(). Since what we only need during recursive call is one previously selected partial string, 'last' can replace role of 'curString'.
CODE
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#define MAX 15
using namespace std;
int k;
vector<string> stringParts;
string cache[MAX + 1][(1 << MAX) + 1];
string restore(int selected = 0, int last = -1) {
if (selected == (1 << k) - 1) {
return stringParts[last];
}
if (last == -1) {
string ret = "";
for (int next = 0; next < k; next++) {
string resultStr = restore(selected + (1 << next), next);
if (ret.empty() || ret.length() > resultStr.length())
ret = resultStr;
}
return ret;
}
string& ret = cache[last][selected];
if (!ret.empty()) {
cout << "cache used in [" << last << "][" << selected << "]" << endl;
return ret;
}
string curString = stringParts[last];
for (int next = 0; next < k; next++) {
if (selected & (1 << next)) continue;
string checkStr = restore(selected + (1 << next), next);
int check = false;
string resultStr;
for (int i = (checkStr.length() > curString.length() ? curString.length() : checkStr.length())
; i > 0; i--) {
if (curString.substr(curString.size() - i, i) == checkStr.substr(0, i)) {
resultStr = curString + checkStr.substr(i, checkStr.length() - i);
check = true;
break;
}
}
if (!check)
resultStr = curString + checkStr;
if (ret.empty() || ret.length() > resultStr.length())
ret = resultStr;
}
return ret;
}
void EraseOverlapped() {
int vectorLen = stringParts.size();
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].length() < stringParts[j].length()) {
string temp = stringParts[i];
stringParts[i] = stringParts[j];
stringParts[j] = temp;
}
}
}
vector<string>::iterator iter;
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].find(stringParts[j]) != string::npos) {
iter = stringParts.begin() + j;
stringParts.erase(iter);
j--;
vectorLen--;
}
}
}
}
int main(void) {
int C;
cin >> C;
for (int testCase = 0; testCase < C; testCase++) {
cin >> k;
for (int i = 0; i < MAX + 1; i++) {
for (int j = 0; j < (1 << MAX) + 1; j++)
cache[i][j] = "";
}
string inputStr;
for (int i = 0; i < k; i++) {
cin >> inputStr;
stringParts.push_back(inputStr);
}
EraseOverlapped();
k = stringParts.size();
string resultStr = restore();
cout << resultStr << endl;
stringParts.clear();
}
}
This algorithm is much slower than the 'ideal' algorithm that the book I'm studying suggests, but it was fast enough to pass this question's time limit.

Print duplicates of strings

I am working a code that will find the amount of duplicated words from a imported file.
The input stream represents a file containing a series of lines. The function should
examine each line looking for consecutive occurrences of the same token on the same line and
print each duplicated token along how many times it appears consecutively. Non-repeated
tokens are not printed.
Here is what I have:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
int main()
{
ifstream in("file.txt");
if (! in)
{
cerr << "Could not open file.txt.";
return EXIT_FAILURE;
}
string str;
int count = 0;
int len=str.length();
while(getline(in,str)){
for(int i = 0; i < len; i++){
if(str.at(i) == str.at(i+1)){
count++;
}
else if(str.at(i) != str.at(i+1)){
i++;
}
}
cout << str << "*" << count << endl;
}
}
The .txt contains:
hello how how are you you you you
I I I am Jack's Jack's smirking smirking smirking smirking smirking revenge
bow wow wow yippee yippee yo yippee yippee yay yay yay
one fish two fish red fish blue fish
It's the Muppet Show, wakka wakka wakka
The output should be:
how*2 you*4
I*3 Jack's*2 smirking*5
wow*2 yippee*2 yippee*2 yay*3
wakka*3
a=list('this is my laptop')
b=list(set(a))
for i in b:
if i==' ':
continue
c=a.count(i)
if c>1:
print('{} is {}'.format(i,c))
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
ifstream in("file.txt");
if(!in){
cerr << "Could not open file.txt.";
return EXIT_FAILURE;
}
string str;
string str2;
string n;
string tab[100];
string tab3[100];
unsigned int tab2[100];
unsigned int tab4[100];
unsigned int i = 0;
unsigned int k = 0;
unsigned int l = 0;
unsigned int tablenght;
unsigned int tablenght2;
k = 0;
//it reads every line of text in file str2
while(getline(in,str2)){
//it add every line of text str2 to str so you get whole file text
str += str2;
str += ' ';
//you need to add a character to mark where was the new line
str += "0 ";
}
for(i = 0; i < str.length(); i++){
/*you check every single character in string str if that char is not
space than it writes it to string table tab, if that char is space than it
adds one to your index so it will write down the next word in next
index of table tab*/
if(str[i] != ' '){
tab[k] += str[i];
}else{
k++;
//that is for two spaces
if(str[i+1] == ' '){
k--;
}
}
}
//k+1 is actually how many words and indexes you wrote to table tab
tablenght = k+1;
l = 0;
k = 0;
for(i = 0; i < tablenght; i++){
//you need to reset the number of repeats k to zero if you go to another line
if(tab[i] == "0"){
k = 0;
}
//there you get the number k how many times does some word repeats itself
if(tab[i] == tab[i+1]){
k++;
//you need to reset k if tab current is not equal to tab next
}else{
k = 0;
}
//there you store k values into integer table tab2
tab2[l] = k+1;
l++;
}
l = 0;
/*there you need to check if current string of table tab is equal to next string
in table tab and if it is you need to set next string to tab3[l] if you dont do
that you get something like that you*4 you*4 you*4 you*4 instead of only you*4*/
for(i = 0; i < tablenght-1; i++){
if(tab[i] == tab[i+1]){
tab3[l] = tab[i+1];
tab4[l] = tab2[i];
}else{
l++;
}
if(tab[i+1] == "0"){
tab3[l] = tab[i+1];
}
k++;
}
tablenght2 = l;
//there you cout both tables
for(i = 0; i < tablenght2; i++){
/*you need to check if number is bigger than 1 because it need to cout only
the words that repeats itself for more than one time than you need to check
that table tab3 doesnt contain string with zero that we previously added
that we could check later if it needs to go in another line and we
need to check that tab3 index is not empty*/
if(tab4[i] > 1 && tab3[i] != "0" && !tab3[i].empty()){
cout << tab3[i] << "*" << tab4[i] << " ";
}
/*thats the zero that we wrote to table in the begining and that we can now
write a new line*/
if(tab3[i] == "0"){
cout << endl;
}
}
return 0;
}

remove commas from string

I created a program in C++ that remove commas (,) from a given integer. i.e. 2,00,00 would return 20000. I am not using any new space. Here is the program I created:
void removeCommas(string& str1, int len)
{
int j = 0;
for (int i = 0; i < len; i++)
{
if (str1[i] == ',')
{
continue;
}
else
{
str1[j] = str1[i];
j++;
}
}
str1[j] = '\0';
}
void main()
{
string str1;
getline(cin, str1);
int i = str1.length();
removeCommas(str1, i);
cout << "the new string " << str1 << endl;
}
Here is the result I get:
Input : 2,000,00
String length =8
Output = 200000 0
Length = 8
My question is that why does it show the length has 8 in output and shows the rest of string when I did put a null character. It should show output as 200000 and length has 6.
Let the standard library do the work for you:
#include <algorithm>
str1.erase(std::remove(str1.begin(), str1.end(), ','), str1.end());
If you don't want to modify the original string, that's easy too:
std::string str2(str1.size(), '0');
str2.erase(std::remove_copy(str1.begin(), str1.end(), str2.begin(), ','), str2.end());
You need to do a resize instead at the end.
Contrary to popular belief an std::string CAN contain binary data including 0s. An std::string 's .size() is not related to the string containing a NULL termination.
std::string s("\0\0", 2);
assert(s.size() == 2);
The answer is probably that std::strings aren't NUL-terminated. Instead of setting the end+1'th character to '\0', you should use str.resize(new_length);.
Edit: Also consider that, if your source string has no commas in it, then your '\0' will be written one past the end of the string (which will probably just happen to work, but is incorrect).
The std::srting does not terminate with \0, you are mixing this with char* in C. So you should use resize.
The solution has already been posted by Fred L.
In a "procedural fashion" (without "algorithm")
your program would look like:
void removeStuff(string& str, char character)
{
size_t pos;
while( (pos=str.find(character)) != string::npos )
str.erase(pos, 1);
}
void main()
{
string str1;
getline(cin, str1);
removeStuff(str1, ',');
cout<<"the new string "<<str1<<endl;
}
then.
Regards
rbo
EDIT / Addendum:
In order to adress some efficiency concerns of readers,
I tried to come up with the fastest solution possible.
Of course, this should kick in on string sizes over
about 10^5 characters with some characters to-be-removed
included:
void fastRemoveStuff(string& str, char character)
{
size_t len = str.length();
char *t, *buffer = new char[len];
const char *p, *q;
t = buffer, p = q = str.data();
while( p=(const char*)memchr(q, character, len-(p-q)) ) {
memcpy(t, q, p-q);
t += p-q, q = p+1;
}
if( q-str.data() != len ) {
size_t tail = len - (q-str.data());
memcpy(t, q, tail);
t += tail;
}
str.assign(buffer, t-buffer);
delete [] buffer;
}
void main()
{
string str1 = "56,4,44,55,5,55"; // should be large, 10^6 is good
// getline(cin, str1);
cout<<"the old string " << str1 << endl;
fastRemoveStuff(str1, ',');
cout<<"the new string " << str1 << endl;
}
My own procedural version:
#include <string>
#include <cassert>
using namespace std;
string Remove( const string & s, char c ) {
string r;
r.reserve( s.size() );
for ( unsigned int i = 0; i < s.size(); i++ ) {
if ( s[i] != c ) {
r += s[i];
}
}
return r;
}
int main() {
assert( Remove( "Foo,Bar,Zod", ',' ) == "FooBarZod" );
}
Here is the program:
void main()
{
int i ;
char n[20] ;
clrscr() ;
printf("Enter a number. ") ;
gets(n) ;
printf("Number without comma is:") ;
for(i=0 ; n[i]!='\0' ; i++)
if(n[i] != ',')
putchar(n[i]) ;
getch();
}
For detailed description you can refer this blog: http://tutorialsschool.com/c-programming/c-programs/remove-comma-from-string.php
The same has been discussed in this post: How to remove commas from a string in C
Well, if youre planing to read from a file using c++. I found a method, while I dont think thats the best method though, but after I came to these forums to search for help before, I think its time to contribute with my effort aswell.
Look, here is the catch, what I'm going to present you is part of the source code of the map editor Im building on right now, that map editor obviously has the purpose to create maps for a 2D RPG game, the same style as the classic Pokemon games for example. But this code was more towards the development of the world map editor.
`int strStartPos = 0;
int strSize = 0;
int arrayPointInfoDepth = 0;
for (int x = 0; x < (m_wMapWidth / (TileSize / 2)); x++) {
for (int y = 0; y < (m_wMapHeight / (TileSize / 2)); y++) {
if (ss >> str) {
for (int strIterator = 0; strIterator < str.length(); strIterator++) {
if (str[strIterator] == ',') {`
Here we need to define the size of the string we want to extract after the previous comma and before the next comma
`strSize = strIterator - strStartPos;`
And here, we do the actual transformation, we give to the vector that is a 3D vector btw the string we want to extract at that moment
`m_wMapPointInfo[x][y][arrayPointInfoDepth] = str.substr(strStartPos, strSize);`
And here, we just define that starting position for the next small piece of the string we want to extract, so the +1 means that after the comma we just passed
strStartPos = strIterator + 1;
Here, well since my vector has only 6 postions that is defined by WorldMapPointInfos we need to increment the third dimension of the array and finally do a check point where if the info has arrived the number 6 then break the loop
arrayPointInfoDepth++;
if (arrayPointInfoDepth == WorldMapPointInfos) {
strStartPos = 0;
arrayPointInfoDepth = 0;
break;
}
}
}
}
}
}
Either way on my code, think abt that the vector is just a string, thats all you need to know, hope this helps though :/
Full view:
int strStartPos = 0;
int strSize = 0;
int arrayPointInfoDepth = 0;
for (int x = 0; x < (m_wMapWidth / (TileSize / 2)); x++) {
for (int y = 0; y < (m_wMapHeight / (TileSize / 2)); y++) {
if (ss >> str) {
for (int strIterator = 0; strIterator < str.length(); strIterator++) {
if (str[strIterator] == ',') {
strSize = strIterator - strStartPos;
m_wMapPointInfo[x][y][arrayPointInfoDepth] = str.substr(strStartPos, strSize);
strStartPos = strIterator + 1;
arrayPointInfoDepth++;
if (arrayPointInfoDepth == WorldMapPointInfos) {
strStartPos = 0;
arrayPointInfoDepth = 0;
break;
}
}
}
}
}
}