[C++] Segmentation Fault {C++ Novice Programmer}

A

AMT2K5

Hello guys.

I have a function, cleanSpace [which takes in a string such as
"this is\ta\ta a test". It cleans it up by removing new
lines/tabs and multiple/trailing and inbetween whitespace. I am
recieving a segmentation fault on one line when I apply it to a second
program [my second school assignment]. I was told from another source
that the problem is, is that the function is acting on constant string
literal. To fix this I was told to take the incoming string, copy it to
a buffer, work on the buffer and copy the buffer back to the original.
I tried but no sucess.

The seg fault is shown after the code snippet below.


int Account::cleanSpace(char c[])
{
int i=0,
j=0,
k=0,
m=0;

/* Ultimately this loop will scan for new lines and tabs and replace
them
with spaces. */
for(i=0; c; i++)
{
if(c == '\n' || c == '\t')
c = ' ';
}

/* For loop finds character starting point. */
for(i=0; c == ' '; i++)
{
c[m] = c[i+1];
}

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}

/* For loop removes trailing spaces. */
for(i = strlen(c) - 1; c == ' '; i--)
{
c = '\0';
}

/*For loop removes excess spaces. */
for(i = 0; c; i++)
{
if(c == ' ' && c[i+1] == ' ')
{
j = i;

while(c[j] == ' ')
{
j++;
}

for(k = i + 1; c[k]; k++, j++)
{
c[k] = c[j];
}
j=0;
}
}
return strlen(c);
}


Here is the function that calls it


int Account::changeCustomerInfo(char c[])
{
int result = 0;
char temp[251];
result = strlen(c) - 250;

cleanSpace(c); //Calls the cleanSpace function

if(strlen(c) <= 250){
strcpy(this->customer, c);
}
else{
for(int i = 0; i < 250; i++){
temp = c;
}
strcpy(this->customer, temp);}

if(strlen(c) > 250){
return result;}

else return 0;
}


I recieve the seg fault on this code snippet below [which is found in
the cleanSpace function]

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}



So by working with
int Account::cleanSpace(char c[]) function, how can I make it work not
on a string literal.

Thanks in advance. Appreciate any help whatsoever.
 
H

Howard

AMT2K5 said:
Hello guys.

I have a function, cleanSpace [which takes in a string such as
"this is\ta\ta a test". It cleans it up by removing new
lines/tabs and multiple/trailing and inbetween whitespace. I am
recieving a segmentation fault on one line when I apply it to a second
program [my second school assignment]. I was told from another source
that the problem is, is that the function is acting on constant string
literal. To fix this I was told to take the incoming string, copy it to
a buffer, work on the buffer and copy the buffer back to the original.
I tried but no sucess.

The seg fault is shown after the code snippet below.


int Account::cleanSpace(char c[])
{
int i=0,
j=0,
k=0,
m=0;

/* Ultimately this loop will scan for new lines and tabs and replace
them
with spaces. */
for(i=0; c; i++)
{
if(c == '\n' || c == '\t')
c = ' ';
}

/* For loop finds character starting point. */
for(i=0; c == ' '; i++)
{
c[m] = c[i+1];
}

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}

/* For loop removes trailing spaces. */
for(i = strlen(c) - 1; c == ' '; i--)
{
c = '\0';
}

/*For loop removes excess spaces. */
for(i = 0; c; i++)
{
if(c == ' ' && c[i+1] == ' ')
{
j = i;

while(c[j] == ' ')
{
j++;
}

for(k = i + 1; c[k]; k++, j++)
{
c[k] = c[j];
}
j=0;
}
}
return strlen(c);
}


Here is the function that calls it


int Account::changeCustomerInfo(char c[])
{
int result = 0;
char temp[251];
result = strlen(c) - 250;

cleanSpace(c); //Calls the cleanSpace function

if(strlen(c) <= 250){
strcpy(this->customer, c);
}
else{
for(int i = 0; i < 250; i++){
temp = c;
}
strcpy(this->customer, temp);}

if(strlen(c) > 250){
return result;}

else return 0;
}


I recieve the seg fault on this code snippet below [which is found in
the cleanSpace function]

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}



So by working with
int Account::cleanSpace(char c[]) function, how can I make it work not
on a string literal.

Thanks in advance. Appreciate any help whatsoever.


I didn't throughly analyze all conditions, but on the strings "XXX\t\n" and
" X ", it worked fine for me. (I substituted the member customer for a
local char[500] array, and made the functions global, but that shouldn't
affect things unless you've got other problems in the class that end up
causing this crash sometime later.) You should try debugging the app and
seeing what the values of c,i and m are the time it crashes. Perhaps
there's some condition you're not accounting for properly.

-Howard
 
D

David Lee Conley

AMT2K5 said:
Hello guys.

I have a function, cleanSpace [which takes in a string such as
"this is\ta\ta a test". It cleans it up by removing new
lines/tabs and multiple/trailing and inbetween whitespace. I am
recieving a segmentation fault on one line when I apply it to a second
program [my second school assignment]. I was told from another source
that the problem is, is that the function is acting on constant string
literal. To fix this I was told to take the incoming string, copy it to
a buffer, work on the buffer and copy the buffer back to the original.
I tried but no sucess.

The seg fault is shown after the code snippet below.


int Account::cleanSpace(char c[])
{
int i=0,
j=0,
k=0,
m=0;

/* Ultimately this loop will scan for new lines and tabs and replace
them
with spaces. */
for(i=0; c; i++)
{
if(c == '\n' || c == '\t')
c = ' ';
}

/* For loop finds character starting point. */
for(i=0; c == ' '; i++)
{
c[m] = c[i+1];
}

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}

/* For loop removes trailing spaces. */
for(i = strlen(c) - 1; c == ' '; i--)
{
c = '\0';
}

/*For loop removes excess spaces. */
for(i = 0; c; i++)
{
if(c == ' ' && c[i+1] == ' ')
{
j = i;

while(c[j] == ' ')
{
j++;
}

for(k = i + 1; c[k]; k++, j++)
{
c[k] = c[j];
}
j=0;
}
}
return strlen(c);
}


Here is the function that calls it


int Account::changeCustomerInfo(char c[])
{
int result = 0;
char temp[251];
result = strlen(c) - 250;

cleanSpace(c); //Calls the cleanSpace function

if(strlen(c) <= 250){
strcpy(this->customer, c);
}
else{
for(int i = 0; i < 250; i++){
temp = c;
}
strcpy(this->customer, temp);}

if(strlen(c) > 250){
return result;}

else return 0;
}


I recieve the seg fault on this code snippet below [which is found in
the cleanSpace function]

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}



So by working with
int Account::cleanSpace(char c[]) function, how can I make it work not
on a string literal.

Thanks in advance. Appreciate any help whatsoever.


I'm taking C and C++ classes right now. The cpp file I attached contains a
program I wrote using C to take user input from the keyboard (whether it's
got letters, numbers, spaces, or other characters), strips all
non-alphabetic characters, removes all spaces, and puts it back into a
sentence. Of course the requirement for this particular program was to
translate English into Pig Latin, so it does some things you don't want.

I make no guarantees about the code (I'm still learning, too). You'll
notice it's in a cpp file and not a c file because I kept getting memory
errors from the executable when using Dev-C++; those errors went away when I
compiled it in an empty VisualC++ project. Maybe somebody else could point
out why.

Dave
 
N

Nagarajan Makala

I was told from another source
I think you didn't fix problem right.

You are still working on const string.

Fix:

You are actually making copy of string into "temp". But you are not
passing temp to "changeCustomerInfo()". You are still passing "c" to
"changeCustomerInfo()". "c" is const string, that is why the crash.

Instead you should pass "temp"

-Nagarajan Makala
AMT2K5 said:
Hello guys.

I have a function, cleanSpace [which takes in a string such as
"this is\ta\ta a test". It cleans it up by removing new
lines/tabs and multiple/trailing and inbetween whitespace. I am
recieving a segmentation fault on one line when I apply it to a second
program [my second school assignment]. I was told from another source
that the problem is, is that the function is acting on constant string
literal. To fix this I was told to take the incoming string, copy it to
a buffer, work on the buffer and copy the buffer back to the original.
I tried but no sucess.

The seg fault is shown after the code snippet below.


int Account::cleanSpace(char c[])
{
int i=0,
j=0,
k=0,
m=0;

/* Ultimately this loop will scan for new lines and tabs and replace
them
with spaces. */
for(i=0; c; i++)
{
if(c == '\n' || c == '\t')
c = ' ';
}

/* For loop finds character starting point. */
for(i=0; c == ' '; i++)
{
c[m] = c[i+1];
}

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}

/* For loop removes trailing spaces. */
for(i = strlen(c) - 1; c == ' '; i--)
{
c = '\0';
}

/*For loop removes excess spaces. */
for(i = 0; c; i++)
{
if(c == ' ' && c[i+1] == ' ')
{
j = i;

while(c[j] == ' ')
{
j++;
}

for(k = i + 1; c[k]; k++, j++)
{
c[k] = c[j];
}
j=0;
}
}
return strlen(c);
}


Here is the function that calls it


int Account::changeCustomerInfo(char c[])
{
int result = 0;
char temp[251];
result = strlen(c) - 250;

cleanSpace(c); //Calls the cleanSpace function

if(strlen(c) <= 250){
strcpy(this->customer, c);
}
else{
for(int i = 0; i < 250; i++){
temp = c;
}
strcpy(this->customer, temp);}

if(strlen(c) > 250){
return result;}

else return 0;
}


I recieve the seg fault on this code snippet below [which is found in
the cleanSpace function]

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}



So by working with
int Account::cleanSpace(char c[]) function, how can I make it work not
on a string literal.

Thanks in advance. Appreciate any help whatsoever.


I didn't throughly analyze all conditions, but on the strings "XXX\t\n" and
" X ", it worked fine for me. (I substituted the member customer for a
local char[500] array, and made the functions global, but that shouldn't
affect things unless you've got other problems in the class that end up
causing this crash sometime later.) You should try debugging the app and
seeing what the values of c,i and m are the time it crashes. Perhaps
there's some condition you're not accounting for properly.

-Howard
 
A

AMT2K5

That makes sense, thanks. Although I am unsure where I would declare
and state what temp is.

Original call


void Account::init(char c[], char num[], int b)
{
changeCustomerInfo(c);
changeAccountNumber(num);
changeBalance(b);
}

I cant do the following though, because temp would just be empty.

void Account::init(char c[], char num[], int b)
{
char temp[300];

changeCustomerInfo(temp);
changeAccountNumber(num);
changeBalance(b);
}


What am I overlooking here?

Nagarajan said:
I think you didn't fix problem right.

You are still working on const string.

Fix:

You are actually making copy of string into "temp". But you are not
passing temp to "changeCustomerInfo()". You are still passing "c" to
"changeCustomerInfo()". "c" is const string, that is why the crash.

Instead you should pass "temp"

-Nagarajan Makala
AMT2K5 said:
Hello guys.

I have a function, cleanSpace [which takes in a string such as
"this is\ta\ta a test". It cleans it up by removing new
lines/tabs and multiple/trailing and inbetween whitespace. I am
recieving a segmentation fault on one line when I apply it to a second
program [my second school assignment]. I was told from another source
that the problem is, is that the function is acting on constant string
literal. To fix this I was told to take the incoming string, copy it to
a buffer, work on the buffer and copy the buffer back to the original.
I tried but no sucess.

The seg fault is shown after the code snippet below.


int Account::cleanSpace(char c[])
{
int i=0,
j=0,
k=0,
m=0;

/* Ultimately this loop will scan for new lines and tabs and replace
them
with spaces. */
for(i=0; c; i++)
{
if(c == '\n' || c == '\t')
c = ' ';
}

/* For loop finds character starting point. */
for(i=0; c == ' '; i++)
{
c[m] = c[i+1];
}

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}

/* For loop removes trailing spaces. */
for(i = strlen(c) - 1; c == ' '; i--)
{
c = '\0';
}

/*For loop removes excess spaces. */
for(i = 0; c; i++)
{
if(c == ' ' && c[i+1] == ' ')
{
j = i;

while(c[j] == ' ')
{
j++;
}

for(k = i + 1; c[k]; k++, j++)
{
c[k] = c[j];
}
j=0;
}
}
return strlen(c);
}


Here is the function that calls it


int Account::changeCustomerInfo(char c[])
{
int result = 0;
char temp[251];
result = strlen(c) - 250;

cleanSpace(c); //Calls the cleanSpace function

if(strlen(c) <= 250){
strcpy(this->customer, c);
}
else{
for(int i = 0; i < 250; i++){
temp = c;
}
strcpy(this->customer, temp);}

if(strlen(c) > 250){
return result;}

else return 0;
}


I recieve the seg fault on this code snippet below [which is found in
the cleanSpace function]

/* For loop moves all characters next to the first found character.
*/
for(i++; c; i++)
{
c[++m] = c;
}



So by working with
int Account::cleanSpace(char c[]) function, how can I make it work not
on a string literal.

Thanks in advance. Appreciate any help whatsoever.


I didn't throughly analyze all conditions, but on the strings "XXX\t\n" and
" X ", it worked fine for me. (I substituted the member customer for a
local char[500] array, and made the functions global, but that shouldn't
affect things unless you've got other problems in the class that end up
causing this crash sometime later.) You should try debugging the app and
seeing what the values of c,i and m are the time it crashes. Perhaps
there's some condition you're not accounting for properly.

-Howard
 
L

Larry I Smith

AMT2K5 said:
Hello guys.

I have a function, cleanSpace [which takes in a string such as
"this is\ta\ta a test". It cleans it up by removing new
lines/tabs and multiple/trailing and inbetween whitespace. I am
recieving a segmentation fault on one line when I apply it to a second
program [my second school assignment]. I was told from another source
that the problem is, is that the function is acting on constant string
literal. To fix this I was told to take the incoming string, copy it to
a buffer, work on the buffer and copy the buffer back to the original.
I tried but no sucess.

[snip]



Thanks in advance. Appreciate any help whatsoever.



Here's some alternatives. Compile and run this program
to see how it works.

// cleanSpace.cpp
// trims leading and trailing whitespace from a string and
// replaces multiple sequential whitespace chars within
// the string with a single space.

// for cin and cout:
#include <iostream>

// for std::string:
#include <string>

// for std::istringstream and std::eek:stringstream
#include <sstream>

// for strcpy() and strdup()
#include <cstring>

// a version using a ref to a std::string as input.
// the input string ('str') is modified.
int cleanSpace(std::string& str)
{
if (0 == str.length())
return 0;

// no words read from the input yet
int wordCount = 0;

// make a string input stream from 'str'
std::istringstream wordsIn(str);

// make a string output stream to hold the result
std::eek:stringstream wordsOut;

// we'll read each word from the input string into 'word'
std::string word;

// while there is data in the input string stream
while (wordsIn)
{
// skip any leading whitespace and read the next word
// into 'word'
wordsIn >> word;

// if we actually read a word (i.e. we havn't reached
// the end of the input data
if (wordsIn)
{
// if we have already put at least one word
// to the output string, append a blank before
// we write the next word to the output string
if (wordCount)
wordsOut << ' ';

// append the word just read from the input string
// to the output string
wordsOut << word;

// erase the content of 'word' so it's ready to
// receive the next word read from the input string
word.erase();

// increment the count of words read from the input
// string
wordCount++;
}
}

// replace the original contents of 'str' with
// the content of the output string stream
str = wordsOut.str();

// return the final number of chars in 'str'
return str.length();
}


// a version using a char array as input.
// the input array ('c') is modified.
int cleanSpace(char * c)
{
if (NULL == c)
return 0;

int wordCount = 0;

// make an input string stream from the contents of 'c'.
std::istringstream wordsIn(c);

std::eek:stringstream wordsOut;
std::string word;

while (wordsIn)
{
wordsIn >> word;

if (wordsIn)
{
if (wordCount)
wordsOut << ' ';

wordsOut << word;
word.erase();
wordCount++;
}
}

// copy the contents of the output string stream
// to 'c' - replacing the original contents of 'c'
strcpy(c, wordsOut.str().c_str());

return strlen(c);
}

#if 0
// an alternate approach for using a char array.
// makes a string from the array, calls cleanSpace(string),
// then copies the result to the original input array ('c')
int cleanSpace(char * c)
{
if (NULL == c)
return 0;

int len;
std::string str(c);

len = cleanSpace(str);
strcpy(c, str.c_str());

return len;
}
#endif

int main()
{
int len;
char * c;
std::string s;

std::cout << "enter a string: ";
std::getline(std::cin, s);

// make a copy of the input string as a char array
c = strdup(s.c_str());

// call the version of cleanSpace() that takes a string
len = cleanSpace(s);
std::cout << "string len " << len << ": '" << s
<< "'" << std::endl;

// call the version of cleanSpace that takes a char array
len = cleanSpace(c);
std::cout << "c[] len " << len << ": '" << c
<< "'" << std::endl;

return 0;
}

Regards,
Larry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top