segmentation fault(core dumped) in C dealing with getchar - c++

I try to read a formula full of -,(,),|,&,>,= characters. I want to skip the blanks and end-of-line characters and put the others in an array to use them efficiently.
The code is:
int main()
{
char *array;
int i=0,j;
char c=getchar();
array=(char*)malloc(sizeof(char));
while (c != EOF)
{
if( islower(c) || (c!=' ' && c!='\n'))
{
array[i]=c;
i++;
array=(char*)realloc(array,sizeof(char)*(i+1));
}
}
}
My input is:
-(-(a&k) > ( -((a|-k)
|c ))
but it gives me segmentation fault. What should I do?

The problem is that you are managing memory yourself and that you are never changing the value of c which, if it's originally different from EOF, will cause an infinite loop. Use std::string:
int main() {
std::string array;
char c = getchar();
while (c != EOF) {
if(islower(c) || (c!=' ' && c!='\n'))
array.push_back(c);
c = getchar();
}
}
Live demo
Not only this is easier to read and to write, but it is also much more efficient than keep reallocating memory at every loop.

for C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(){
char *array;
int ch, i=0, capacity = 16;
array = malloc(capacity);
while(EOF!=(ch = getchar())){//It is necessary to receive an int return value is in order to properly compare EOF.
if(!isspace(ch)){//islower not necessary when OR(||) condition
array[i++]=ch;
if(i==capacity)//Efficiency is not good of character by character
array = realloc(array, capacity += 16);
}
}
array[i] = '\0';
printf("%s\n", array);
free(array);
return 0;
}

Related

Processing strings with toupper() causing an infinite loop

I'm trying to write a program to convert one letter of each word to uppercase. argv[1] is a number like 3. If argv[1] is 3, only the third letter of each word should be uppercase and the others lowercase.
I wrote this disaster of a code, and it's stuck in an infinite loop that only displays the first input char repeatedly.
I need help with the logic.
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int c; // yes, read chars in as ints.
int ncounter = atoi(argv[1]);
int cchecker = 0;
c = cin.get();
while (!cin.eof())
{
if (c == ' ')
{
cchecker = 0;
}
else
{
if (cchecker == ncounter)
{
c = (toupper(c));
cchecker++;
}
else
{
c = (tolower(c));
cchecker++;
}
}
cout.put('\n'); // sometimes this is needed: you'll know when
}
}
Update here's new code, it works almost perfect, except it sometimes doesn't uppercase the first word, kinda strange.
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
int main (int argc, char *argv[])
{
int c ; // yes, read chars in as ints.
int ncounter = atoi(argv[1]);
int cchecker = 0;
c = cin.get() ;
while (!cin.eof())
{
if (c == ' ')
{
cchecker = 0;
cout.put (c);
c = cin.get ();
cchecker++;
}
else
{
if (cchecker == ncounter)
{
cout.put (toupper(c));
c = cin.get() ;
cchecker++;
}
else
{
cout.put (tolower(c));
c = cin.get() ;
cchecker++;
}
}
}
cout.put('\n') ; // sometimes this is needed: you'll know when
}
while (!cin.eof())
Your loop condition states, that the loop ends if eofbit of the standard input stream (represented by the std::cin object) was set in the last iteration. Eofbit would be set upon reading from the standard input when there is no more characters there.
it's stuck in an infinite loop
Your loop never reads from the standard input, and therefore the state of the loop condition can never change. If the loop is entered, it will never stop.
As others have stated, you are reading from std::cin only one time, before entering the loop, so you get stuck in an infinite loop because you never call cin.get() again inside the loop so cin.eof() has a chance to change value. Though, you should consider using while (cin.get(ch)) instead of while (!cin.eof()).
But, why are you reading from std::cin one char at a time to begin with? You say you want to change letters in words, so you should be reading whole words, not individual characters.
Try using operator>> in a loop to read a whole word, replacing the Nth char in that word, eg:
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cctype>
char my_toupper(char ch)
{
return std::toupper(static_cast<unsigned char>(ch));
}
char my_tolower(char ch)
{
return std::tolower(static_cast<unsigned char>(ch));
}
int main(int argc, char *argv[])
{
int ncounter = std::atoi(argv[1]);
std::string word;
while (cin >> word)
{
std::transform(word.begin(), word.end(), word.begin(), my_tolower);
if (word.size() >= ncounter)
word[ncounter-1] = my_toupper(word[ncounter-1]);
std::cout << word << "\n";
}
return 0;
}

How to count characters that appear twice consecutively

I'm using C++. So far, my code goes like this:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <windows.h>
int main() {
char word[100]; int ctr, count = 0;
printf("Enter string: "); gets(word);
ctr = 1;
while (word[ctr] != '\0') {
if (word[ctr-1] == word[ctr]) count++;
ctr++;
}
printf("%d", count);
return 0;
}
Sample Run
Enter string: mississippi
3
Enter string: mmmmrrnzzz
6
I've got the first sample run correctly (mississippi) with only 3 characters appearing twice consecutively but not on the second sample run (mmmmrrnzzz) with output 6.
My problem is that, it should not be 6 but 4 instead. 1 for the first two consecutive m, another separate 1 for the next two consecutive m, 1 for r, and 1 for z. I want a separate count for the first "mm" and the second "mm" and also for the "zz" but I don't know how.
I'm a freshman and very new to programming. I wish I could explain better. I'm hoping you could help me. Thank you.
In case of multiple couples like mmmm you need to make a double incrementation of your counter:
#include <stdio.h>
#include <string.h>
int main()
{
char word[100];
int ctr;
int count = 0;
printf("Enter string: ");
gets(word);
int len = strlen(word);
ctr = 1;
while (ctr<len) {
if (word[ctr-1] == word[ctr])
{
count++;
ctr++;
}
ctr++;
}
printf("%d", count);
return 0;
}
First of all the program looks like a C program. In fact you are not using C++. You are using C.:) At least for example in C++ you should use header
#include <cstdio>
instead of
#include <stdio.h>
and so on.
And moreover it has a bug because in general the string can be empty. In this case the condition of the loop skips the first zero-terminating character and the program has undefined behaviour.
Here is a correct approach
#include <stdio.h>
int main( void )
{
const char *s = "mmmmrrnzzz";
size_t count = 0;
while ( *s++ )
{
if ( *s == *( s - 1) )
{
++count;
++s;
}
}
printf( "count = %zu\n", count );
}
The output is
count = 4
Take into account that function gets is unsafe and is not supported by the C (or C++) Standard any more.
You should use function fgets instead of gets.
This will work
#include <stdio.h>
#include <string.h>
int main() {
char word[100]; int ctr, count = 0;
printf("Enter string: "); gets(word);
int len=strlen(word);
ctr = 1;
while (ctr<len) {
if (word[ctr-1] == word[ctr])
{
count++;
ctr++;
}
ctr++;
}
printf("%d", count);
return 0;
}
A standard library version:
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
int count{};
std::string s;
std::cin >> s;
for (auto it = s.begin(); (it = std::adjacent_find(it, s.end())) != s.end(); it += 2)
++count;
std::cout << count << '\n';
}

I get a number 2 when I reverse my string

I wrote this code to reverse strings. It works well, but when I enter short strings like "american beauty," it actually prints "ytuaeb nacirema2." This is my code. I would like to know what is wrong with my code that prints a random 2 at the end of the string. Thanks
// This program prompts the user to enter a string and displays it backwards.
#include <iostream>
#include <cstdlib>
using namespace std;
void printBackwards(char *strPtr); // Function prototype
int main() {
const int SIZE = 50;
char userString[SIZE];
char *strPtr;
cout << "Please enter a string (up to 49 characters)";
cin.getline(userString, SIZE);
printBackwards(userString);
}
//**************************************************************
// Definition of printBackwards. This function receives a *
// pointer to character and inverts the order of the characters*
// within it. *
//**************************************************************
void printBackwards(char *strPtr) {
const int SIZE = 50;
int length = 0;
char stringInverted[SIZE];
int count = 0;
char *strPtr1 = 0;
int stringSize;
int i = 0;
int sum = 0;
while (*strPtr != '\0') {
strPtr++; // Set the pointer at the end of the string.
sum++; // Add to sum.
}
strPtr--;
// Save the contents of strPtr on stringInverted on inverted order
while (count < sum) {
stringInverted[count] = *strPtr;
strPtr--;
count++;
}
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
cout << stringInverted << endl;
}
Thanks.
Your null termination is wrong. You're using == instead of =. You need to change:
stringInverted[count] == '\0';
into
stringInverted[count] = '\0';
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
Should use = here.
What is wrong with your code is that you do not even use strlen for counting the length of the string and you use fixed size strings (no malloc, or, gasp new[]), or the std::string (this is C++)! Even in plain C, not using strlen is always wrong because it is hand-optimized for the processor. What is worst, you have allocated the string to be returned (stringInverted) from the stack frame, which means when the function exits, the pointer is invalid and any time the code "works" is purely accidental.
To reverse a string on c++ you do this:
#include <iostream>
#include <string>
int main() {
std::string s = "asdfasdf";
std::string reversed (s.rbegin(), s.rend());
std::cout << reversed << std::endl;
}
To reverse a string in C99 you do this:
char *reverse(const char *string) {
int length = strlen(string);
char *rv = (char*)malloc(length + 1);
char *end = rv + length;
*end-- = 0;
for ( ; end >= rv; end --, string ++) {
*end = *string;
}
return rv;
}
and remember to free the returned pointer after use. All other answers so far are blatantly wrong :)

strcmp segmentation fault

Here is a problem from spoj. nothing related to algorithms, but just c
Sample Input
2
a aa bb cc def ghi
a a a a a bb bb bb bb c c
Sample Output
3
5
it counts the longest sequence of same words
http://www.spoj.pl/problems/WORDCNT/
The word is less than 20 characters
But when i run it, it's giving segmentation fault. I debugged it using eclipse. Here's where it crashes
if (strcmp(previous, current) == 0)
currentLength++;
with the following message
No source available for "strcmp() at 0x2d0100"
What's the problem?
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
int main(int argc, const char *argv[])
{
int t;
cin >> t;
while (t--) {
char line[20000], previous[21], current[21], *p;
int currentLength = 1, maxLength = 1;
if (cin.peek() == '\n') cin.get();
cin.getline(line, 20000);
p = strtok(line, " '\t''\r'");
strcpy(previous, p);
while (p != NULL) {
p = strtok(NULL, " '\t''\r'");
strcpy(current, p);
if (strcmp(previous, current) == 0)
currentLength++;
else
currentLength = 1;
if (currentLength > maxLength)
maxLength = currentLength;
}
cout << maxLength << endl;
}
return 0;
}
The problem is probably here:
while (p != NULL) {
p = strtok(NULL, " '\t''\r'");
strcpy(current, p);
While p may not be NULL when the loop is entered.
It may be NULL when strcpy is used on it.
A more correct form of the loop would be:
while ((p != NULL) && ((p = strtok(NULL, " \t\r")) != NULL))
{
strcpy(current, p);
Note. Tokenizing a stream in C++ is a lot easier.
std::string token;
std::cin >> token; // Reads 1 white space seoporated word
If you want to tokenize a line
// Step 1: read a single line in a safe way.
std::string line;
std::getline(std::cin, line);
// Turn that line into a stream.
std::stringstream linestream(line);
// Get 1 word at a time from the stream.
std::string token;
while(linestream >> token)
{
// Do STUFF
}
Forgot to check for NULL on strtok, it will return NULL when done and you cannot use that NULL on strcpy, strcmp, etc.
Note that you do a strcpy right after the strtok, you should check for null before doing that using p as a source.
The strtok man page says:
Each call to strtok() returns a pointer to a null-terminated string containing the next
token. This string does not include the delimiting character. If no more tokens are found,
strtok() returns NULL.
And in your code,
while (p != NULL) {
p = strtok(NULL, " '\t''\r'");
strcpy(current, p);
you are not checking for NULL (for p) once the whole string has been parsed. After that you are trying to copy p (which is NULL now) in current and so getting the crash.
You will find that one of previous or current does not point to a null-terminated string at that point, so strcmp doesn't know when to stop.
Use proper C++ strings and string functions instead, rather than mixing C and C++. The Boost libraries can provide a much safer tokeniser than strtok.
You probably undersized current and previous. You should really use std::string for this kind of thing- that's what it's for.
You are doing nothing to check your string lengths before copying them into buffers of size 21. I bet that you are somehow overwriting the end of the buffer.
If you insist on using C strings, I'd suggest using strncmp instead of strcmp. That way, in case you are ending up with a non-null terminated string (which is what I suspect is the case), you can restrict your compare to the max length of the string (in this case 21).
Try this one...
#include <cstdio>
#include <cstring>
#define T(x) strtok(x, " \n\r\t")
char line[44444];
int main( )
{
int t; scanf("%d\n", &t);
while(t--)
{
fgets(line, 44444, stdin);
int cnt = 1, len, maxcnt = 0, plen = -1;
for(char *p = T(line); p != NULL; p = T(NULL))
{
len = strlen(p);
if(len == plen) ++cnt;
else cnt = 1;
if(cnt > maxcnt)
maxcnt = cnt;
plen = len;
}
printf("%d\n", maxcnt);
}
return 0;
}

a simple getch() and strcmp problem

I have this simple problem that gets an input from the user using a function then checks if the input is 'equal' to the "password". However, strcmp would never return my desired value, and the culprit is somewhere in my loop that uses getch() to take each character separately and add them to the character array. I found this out by having printf display the character array. If I type in pass word, the function would display it as pass word ". I have no idea on why the closing double quote and a whitespace was included in the array right after the word I typed in. Any idea? Here's the code. Thanks.
#include <stdio.h>
#include <iostream>
#include <conio.h>
#include <string.h>
int validateUser();
int main()
{
for(int x = 0;x<2;x++)
{
if(validateUser())
{
system("cls");
printf("\n\n\t\t** Welcome **"); break;
}
else
{
system("cls");
printf("\n\n\t\tIntruder Alert!");
system("cls");
}
}
system("PAUSE>nul");
return 0;
}
int validateUser()
{
char password[9];
char validate[] = "pass word";
int ctr = 0, c;
printf("Enter password : ");
do
{
c = getch();
if(c == 32)
{
printf(" ");
password[ctr] = c;
}
if(c != 13 && c != 8 && c != 32 )
{
printf("*");
password[ctr] = c;
}
c++;
}while(c != 13);
return (!strcmp(password, validate));
}
Your char array password does not
have a terminating null char.
You need to ensure that you don't
stuff more than 8 char into
password
Also c++ should be ctr++
.
do {
// stuff char into password.
ctr++;
}while(c != 13 && ctr <8);
password[ctr] = 0;
You're incrementing c in your loop. You should be incrementing ctr. Also, all the stuff everyone else has said (null terminator, only 8 characters, etc).
getch() is a function defined in a non-standard header <conio.h>. Relying on non-standard features is not recommended when you want your code to be portable. :)
do {
// stuff char into password.
++ctr;
} while(c != 13 && ctr < 9);
password[ctr] = '\0';