Segmentation fault in searching for substring in string - c

Im trying to write a method that checks a string to see if it contains a substring. So for example if the user input was "hello" and they were searching the string for "lo" the output would be "true", but if they were searching for "ol" the output would be "false". This is for a class (I'm not looking for someone to do it for me) so i am supposed to do it by hand and not use many built in functions. Right now my code compiles and then gives me a segmentation fault:11.
void subsetCheck(char *string, char *srch){
char str[100];
char search[100];
strcpy(str, string);
strcpy(search, srch);
int i = 0, j = 0, flag = 0;
while(i < strlen(str)){
if(strcmp(str[i],search[j]) == 0){
for(j; j < strlen(search); j++){
if(strcmp(str[i],str[j]) != 0){
j = 0;
break;
}
else{
flag = 1;
}
}
}
i++;
}
if(flag == 1){
printf("TRUE");
}
else{
printf("FALSE");
}
return;
}
I edited my code, which entailed some of the things mentioned in the comments as well as rearranging some for loops and added in comments to try and explain what I think I'm doing at each step.
void subsetCheck(char *string, char *srch){
char str[100];
char search[100];
strcpy(str, string);
strcpy(search, srch);
int i = 0, j = 0, flag = 0, k = 0;
while(i < strlen(str)){
for(j; j <= strlen(search);j++){ //for length of the substring during each i iteration
if(str[i] == search[j]){ //if position i matches first letter in substring go into for loop
for(k; k <= strlen(search);k++){ //create variable k to allow iteration through strin without messing up placement of i, incase entire substrin isnt there
k = i;
if(str[k] != search[j]){ //if string position k doesnt equal position j, reassign both variables and break out of the loop
j = 0;
k = i;
flag = 0;
break;
}
else{ //if it does than assign flag the value of 1 and iterate both variables
flag = 1;
j++;
k++;
}
}
}
}
i++;
}
if(flag == 1){
printf("TRUE");
}
else{
printf("FALSE");
}
return;
}

if(strcmp(str[i],search[j]) == 0){
str[i] and search[j] are already single characters. You should use comparison operators instead of strcmp() to compare between characters.

Related

How to remove all repeated character in character array

I want to remove all the repeated characters from array. here is example.
"aabccdee"
"bd"
I'm doing this C language. use only array, loop, if,else(conditional statements) not using pointer.
#include<stdio.h>
int main() {
char c[10];
char com[10] = {0,};
char result[10] = { 0, };
int cnt = 0;
for (int i = 0; i < 10; i++) {
scanf("%c", &c[i]);
}
for (int i = 0; i < 10; i++) {
for (int j = i+1; j < 10; j++) {
if (c[i] == c[j]) {
com[i] = c[i];
cnt++;
printf("%c", com[i]);
}
}
}
for (int i = 0; i < cnt; i++) {
for (int j = 0; j < 10; j++) {
if (com[i] != c[j]) {
result[j] = c[j];
}
}
}
printf("\n");
for (int i = 0; i < 10; i++) {
printf("%c", result[i]);
}
}
I thought this
Make repeated array
Compare original array to repeated array
Output
But repeated array loop can't looping all original array.
How can I do remove all repeated character?
Not good SO policy to blatantly answer homework, but I rarely do it and thought this was an interesting task. Certainly making no claims on efficiency, but it looks like it works to me. As far as I can tell, the first and last cases are corner cases, so I handle those individually, and use a loop for everything in the middle. If you're not allowed to use strlen, then you can roll your own or use some other method, that's not the primary focus of this problem (would be best to fgets the string from a command line argument).
#include <stdio.h>
#include <string.h>
int main(void)
{
char source[] = "aabccdee";
char result[sizeof(source)] = { 0 };
unsigned resultIndex = 0;
unsigned i = 0;
// do this to avoid accessing out of bounds of source.
if (strlen(source) > 1)
{
// handle the first case, compare index 0 to index 1. If they're unequal, save
// index 0.
if (source[i] != source[i+1])
{
result[resultIndex++] = source[i];
}
// source[0] has already been checked, increment i to 1.
i++;
// comparing to strlen(source) - 1 because in this loop we are comparing the
// previous and next characters to the current. Looping from 1 to second-to-the-
// last char means we stay in bounds of source
for ( ; i < strlen(source) - 1; i++)
{
if (source[i-1] != source[i] && source[i] != source[i+1])
{
// write to result if curr char != prev char AND curr char != next char
result[resultIndex++] = source[i];
}
}
// handle the end. At this point, i == the last index of the string. Compare to
// previous character. If they're not equal, save the last character.
//
if (source[i] != source[i-1])
{
result[resultIndex] = source[i];
}
}
else if (strlen(source) == 1)
{
// if source is only 1 character, then it's trivial
result[resultIndex] = source[i];
}
else
{
// source has no length
fprintf(stderr, "source has no length.\n");
return -1;
}
// print source and result
printf("source = %s\n", source);
printf("result = %s\n", result);
return 0;
}
Various outputs for source:
source = "aabccdee"
result = "bd"
source = "aaee"
result =
source = "a"
result = "a"
source = "abcde"
result = "abcde"
source = "abcdee"
result = "abcd"
source = "aabcde"
result = "bcde"
source = "aaaaaaaaaaaabdeeeeeeee"
result = "bd"
source = ""
source has no length.
first of all before we speak , you have to check this
you need to put a whitespace when scaning a char using scanf
so
scanf("%c", &c[i]);
becomes
scanf(" %c", &c[i]);
secondly your idea is kinda a messy as the result showed you're only handling cases and it doesn't continue verifying the whole array . you need to learn how to shift an array to the right or left
your issue later on that when you shift your table(not completely) you still print out of the size .
so bascilly in general your code should be something like this :
#include<stdio.h>
int main() {
char c[10];
int length=5;
for (int i = 0; i < 5; i++) {
scanf(" %c", &c[i]);
}
int j,k,i;
for(i=0; i<length; i++)
{
for(j=i+1; j<length; j++)
{
if(c[i] == c[j])
{
length--;
for(k=j; k<length; k++)
{
c[k] = c[k + 1];
}
j--;
}
}
}
printf("\n");
for (int i = 0; i < length; i++) {
printf("%c", c[i]);
}
}
you simply take one case and compare it to the rest , if it exists you shift from the position you find for the second time the element and so on

Longest Substring Palindrome issue

I feel like I've got it almost down, but for some reason my second test is coming up with a shorter palindrome instead of the longest one. I've marked where I feel the error may be coming from, but at this point I'm kind of at a loss. Any direction would be appreciated!
#include <stdio.h>
#include <string.h>
/*
* Checks whether the characters from position first to position last of the string str form a palindrome.
* If it is palindrome it returns 1. Otherwise it returns 0.
*/
int isPalindrome(int first, int last, char *str)
{
int i;
for(i = first; i <= last; i++){
if(str[i] != str[last-i]){
return 0;
}
}
return 1;
}
/*
* Find and print the largest palindrome found in the string str. Uses isPalindrome as a helper function.
*/
void largestPalindrome(char *str)
{
int i, last, pStart, pEnd;
pStart = 0;
pEnd = 0;
int result;
for(i = 0; i < strlen(str); i++){
for(last = strlen(str); last >= i; last--){
result = isPalindrome(i, last, str);
//Possible error area
if(result == 1 && ((last-i)>(pEnd-pStart))){
pStart = i;
pEnd = last;
}
}
}
printf("Largest palindrome: ");
for(i = pStart; i <= pEnd; i++)
printf("%c", str[i]);
return;
}
/*
* Do not modify this code.
*/
int main(void)
{
int i = 0;
/* you can change these strings to other test cases but please change them back before submitting your code */
//str1 working correctly
char *str1 = "ABCBACDCBAAB";
char *str2 = "ABCBAHELLOHOWRACECARAREYOUIAMAIDOINEVERODDOREVENNGGOOD";
/* test easy example */
printf("Test String 1: %s\n",str1);
largestPalindrome(str1);
/* test hard example */
printf("\nTest String 2: %s\n",str2);
largestPalindrome(str2);
return 0;
}
Your code in isPalindrome doesn't work properly unless first is 0.
Consider isPalindrome(6, 10, "abcdefghhgX"):
i = 6;
last - i = 4;
comparing str[i] (aka str[6] aka 'g') with str[last-i] (aka str[4] aka 'e') is comparing data outside the range that is supposed to be under consideration.
It should be comparing with str[10] (or perhaps str[9] — depending on whether last is the index of the final character or one beyond the final character).
You need to revisit that code. Note, too, that your code will test each pair of characters twice where once is sufficient. I'd probably use two index variables, i and j, set to first and last. The loop would increment i and decrement j, and only continue while i is less than j.
for (int i = first, j = last; i < j; i++, j--)
{
if (str[i] != str[j])
return 0;
}
return 1;
In isPalindrome, replace the line if(str[i] != str[last-i]){ with if(str[i] != str[first+last-i]){.
Here's your problem:
for(i = first; i <= last; i++){
if(str[i] != str[last-i]){
return 0;
}
}
Should be:
for(i = first; i <= last; i++, last--){
if(str[i] != str[last]){
return 0;
}
}
Also, this:
for(last = strlen(str); last >= i; last--){
Should be:
for(last = strlen(str) - 1; last >= i; last--){

what's wrong with my function (removing string from text file)

I want to write a function which removes certain word from text file. Program works fine but valgrind says something different:
==3411== Source and destination overlap in strcpy(0x51f1c90, 0x51f1c92)
==3411== at 0x4C2C085: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3411== by 0x400AD7: DELTEword (remove2.c:113)
==3411== by 0x4009A1: main (remove2.c:73)
also when I am trying to remove for instance word: "go" sometimes it happens that word "ro" is also removed. Why?
Here's my code:
int DELTEword(char *word, char *KEYword)
{
int i, k = 0, l = 0, length;
char *ptr;
if(word != NULL)
{
length = strlen(KEYword);
for(i = 0; word[i] != '\0'; i++)
{
if(word[i] == KEYword[k])
{
l++;
k++;
}
if(l == length)
{
ptr = &word[i];
strcpy((ptr - length) + 1, ptr + 1);
l = 0;
k = 0;
}
}
return 1;
}
else return 0;
}
Use memmove instead of strcpy to shuffle the data around, as strcpy is not recommended if source and destination is overlapping. memmove is safe to use in overlapping situations..
I think the problem is with the following piece of code
for(i = 0; word[i] != '\0'; i++)
{
if(word[i] == KEYword[k])
{
l++;
k++;
}
}
It does not look for continuous letters. If the letters do not match, then it would continue from the next. I mean the else part handling is missing.
May be this helps. This matches all occurences, I mean the word go in good. Can be tuned to your need.
length = strlen(KEYword);
for(i = 0; word[i] != '\0'; i++)
{
k = i;
l = 0;
for (j = 0; j < length; j++) {
if(word[k] == KEYword[j])
{
l++;
k++;
}
else
{
break;
}
}
/* All letters matched */
if (l == length) {
/* do some stuff */
}
}

How can I implement my anagram and palindrome functions to check the words input by a user?

I got some help earlier fixing up one of the functions I am using in this program, but now I'm at a loss of logic.
I have three purposes and two functions in this program. The first purpose is to print a sentence that the user inputs backwards. The second purpose is to check if any of the words are anagrams with another in the sentence. The third purpose is to check if any one word is a palindrome.
I successfully completed the first purpose. I can print sentences backwards. But now I am unsure of how I should implement my functions to check whether or not any words are anagrams or palindromes.
Here's the code;
/*
* Ch8pp14.c
*
* Created on: Oct 12, 2013
* Author: RivalDog
* Purpose: Reverse a sentence, check for anagrams and palindromes
*/
#include <stdio.h>
#include <ctype.h> //Included ctype for tolower / toupper functions
#define bool int
#define true 1
#define false 0
//Write boolean function that will check if a word is an anagram
bool check_anagram(char a[], char b[])
{
int first[26] = {0}, second[26] = {0}, c = 0;
// Convert arrays into all lower case letters
while(a[c])
{
a[c] = (tolower(a[c]));
c++;
}
c = 0;
while(b[c])
{
b[c] = (tolower(b[c]));
c++;
}
c = 0;
while (a[c] != 0)
{
first[a[c]-'a']++;
c++;
}
c = 0;
while (b[c] != 0)
{
second[b[c]-'a']++;
c++;
}
for (c = 0; c < 26; c++)
{
if (first[c] != second[c])
return false;
}
return true;
}
//Write boolean function that will check if a word is a palindrome
bool palindrome(char a[])
{
int c=0, j, k;
//Convert array into all lower case letters
while (a[c])
{
a[c] = (tolower(a[c]));
c++;
}
c = 0;
j = 0;
k = strlen(a) - 1;
while (j < k)
{
if(a[j++] != a[k--])
return false;
}
return true;
}
int main(void)
{
int i = 0, j = 0, k = 0;
char a[80], terminator;
//Prompt user to enter sentence, store it into an array
printf("Enter a sentence: ");
j = getchar();
while (i < 80)
{
a[i] = j;
++i;
j = getchar();
if (j == '!' || j == '.' || j == '?')
{
terminator = j;
break;
}
else if(j == '\n')
{
break;
}
}
while(a[k])
{
a[k] = (tolower(a[k]));
k++;
}
k = 0;
while(k < i)
{
printf("%c", a[k]);
k++;
}
printf("%c\n", terminator);
//Search backwards through the loop for the start of the last word
//print the word, and then repeat that process for the rest of the words
for(j = i; j >= 0; j--)
{
while(j > -1)
{
if (j == 0)
{
for(k=j;k<i;k++)
{
printf("%c", a[k]);
}
printf("%c", terminator);
break;
}
else if (a[j] != ' ')
--j;
else if (a[j] == ' ')
{
for(k=j+1;k<i;k++)
{
printf("%c", a[k]);
}
printf(" ");
break;
}
}
i = j;
}
//Check if the words are anagrams using previously written function
for( i = 0; i < 80; i++)
{
if (a[i] == ' ')
{
}
}
//Check if the words are palindromes using previously written function
return 0;
}
I was thinking that perhaps I could again search through the array for the words by checking if the element is a space, and if it is, store from where the search started to the space's index-1 in a new array, repeat that process for the entire sentence, and then call my functions on all of the arrays. The issue I am seeing is that I can't really predict how many words a user will input in a sentence... So how can I set up my code to where I can check for anagrams/palindromes?
Thank you everyone!
~RivalDog
Would be better,if you first optimize your code and make it readable by adding comments.Then you can divide the problem in smaller parts like
1.How to count words in a string?
2.How to check whether two words are anagrams?
3.How to check whether a word is palindrome or not?
And these smaller programs you could easily get by Googling. Then your job will be just to integrate these answers. Hope this helps.
To check anagram, no need to calculate number of words and comparing them one by one or whatever you are thinking.
Look at this code. In this code function read_word() is reading word/phrase input using an int array of 26 elements to keep track of how many times each letter has been seen instead of storing the letters itself. Another function equal_array() is to check whether both array a and b (in main) are equal (anagram) or not and return a Boolean value as a result.
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
void read_word(int counts[26]);
bool equal_array(int counts1[26],int counts2[26]);
int main()
{
int a[26] = {0}, b[26] = {0};
printf("Enter first word/phrase: ");
read_word(a);
printf("Enter second word/phrase: ");
read_word(b);
bool flag = equal_array(a,b);
printf("The words/phrase are ");
if(flag)
printf("anagrams");
else
printf("not anagrams");
return 0;
}
void read_word(int counts[26])
{
int ch;
while((ch = getchar()) != '\n')
if(ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')
counts[toupper(ch) - 'A']++;
}
bool equal_array(int counts1[26],int counts2[26])
{
int i = 0;
while(i < 26)
{
if(counts1[i] == counts2[i])
i++;
else
break;
}
return i == 26 ? true : false;
}

Palindrome in C without pointers and recursion

I'm trying to determine if a phrase is a palindrome (a word that is the same from left to rigth) or not but i can't make it work. What's wrong?, i can't use pointers or recursion or string type variables
#include <stdio.h>
#include <string.h>
int main()
{
int i,j = 0,length;
char space = ' ';
char phrase [80],phrase2[80],phrase3[80];
printf("Give me the phrase: ");
gets(phrase);
length = strlen(phrase);
for(i =0; i <= length - 1; i++)
{
if(phrase[i] != space) //Makes the phrase without spaces
{
phrase2[i] = phrase[i];
j++;
}
}
for(i = length -1; i >= 0;i--)
{
if(phrase[i] != space) //Makes the phrase backwards an without spaces
{
phrase3[j] = phrase[i];
j++;
}
}
length = strlen(phrase2);
for(i =0; i <= length -1;i++) //Compare the phrases to know if they are the same
{
if(phrase2[i] != phrase3[i])
{
printf("It's not a palindrome\n");
return 0;
}
}
printf("It's a palindrome\n");
return 0;
}
Try this:
for(i =0, j=0; i <= length - 1; i++)
{
if(phrase[i] != space) //Makes the phrase without spaces
{
phrase2[j] = phrase[i];
j++;
}
}
for(i = length -1, j = 0; i >= 0;i--)
{
if(phrase[i] != space) //Makes the phrase backwards an without spaces
{
phrase3[j] = phrase[i];
j++;
}
}
length = j;
Update
In response to Praetorian's post here's the code to do it without copying the string.
#include <stdio.h>
#include <string.h>
int main()
{
int i, j, length;
char space = ' ';
char phrase[80];
printf("Give me the phrase: ");
gets(phrase);
length = strlen(phrase);
for( i = 0, j = length - 1; i < j; i++, j-- ) {
while (phrase[i] == space) i++;
while (phrase[j] == space) j--;
if( phrase[i] != phrase[j] ) {
printf("It's not a palindrome\n");
return 0;
}
}
printf("It's a palindrome\n");
return 0;
}
Before the 2nd loop you want to set j=0. It should work after that.
PS: If you debugged by printing out your three strings, you would've figured it out in a matter of minutes. When you don't know what goes wrong, print out the values of variables at intermediate steps, so you know where your problem occurs and what it is.
Your question has already been answered by others but I'm posting this code to show that it is not necessary to make the phrase3 copy to hold the reversed string.
#include <stdio.h>
#include <string.h>
int main()
{
int i, j, length, halfLength;
char space = ' ';
char phrase1[80], phrase2[80];
printf("Give me the phrase: ");
gets(phrase1);
length = strlen(phrase1);
for( i = 0, j = 0; i <= length; ++i ) {
if( phrase1[i] != space ) { //Makes the phrase1 without spaces
phrase2[j++] = phrase1[i];
}
}
length = strlen(phrase2);
halfLength = length / 2;
for( i = 0, j = length - 1; i < halfLength; ++i, --j ) {
if( phrase2[i] != phrase2[j] ) {
printf("It's not a palindrome\n");
return 0;
}
}
printf("It's a palindrome\n");
return 0;
}
This is what I came up with:
#include <stdio.h>
void main() {
char a[50],b[50];
int i=0,j,ele,test=0,x;
while((a[i]=getchar())!='\n') {
if(a[i]!=' ' && a[i]!=',') //do not read whitespaces and commas(for palindromes like "Ah, Satan sees Natasha")
i++;
}
a[i]='\0';
ele=strlen(a);
// Convert string to lower case (like reverse of Ava is avA and they're not equal)
for(i=0; i<ele; i++)
if(a[i]>='A'&&a[i]<='Z')
a[i] = a[i]+('a'-'A');
x = ele-1;
for(j=0; j<ele; j++) {
b[j] = a[x];
x--;
}
for(i=0; i<ele; i++)
if(a[i]==b[i])
test++;
if(test==ele)
printf("You entered a palindrome!");
else
printf("That's not a palindrome!");
}
Probably not the best way for palindromes, but I'm proud I made this on my own took me 1 hour :( lol
Why not use a std::stack? You will need two loops, each iterating the length of the input string. In the first loop, go through the input string once, pushing each character ont the stack. In the second loop, pop a character off the stack and compare it with the character at the index. If you get a mismatch before the loop ends, you don't have a palindrome. The nice thing with this is that you don't have to worry about the even/odd length corner-case. It will just work.
(If you are so inclined, you can use one stack (LIFO) and one queue (FIFO) but that doesn't substantially change the algorithm).
Here's the implementation:
bool palindrome(const char *s)
{
std::stack<char> p; // be sure to #include <stack>
for(int i = 0; s[i] != 0; i++)
p.push(s[i]);
for(int i = 0; s[i] != 0; i++)
{
if(p.top() != s[i])
return false; // not a palindrome!
p.pop();
}
return true;
}
Skipping spaces is left as an exercise to the reader ;)

Resources