why Segmentation fault: 11 occurred for my C code? - c

I tried to write a function that deletes each character in string s1 that matches any character in the string s2.
Here is the testing code for the squeeze method.
#include <stdio.h>
void squeeze(char s1[], char s2[]);
int main()
{
char s1[20] = "HelloWorld", s2[20] = "ol";
squeeze(s1, s2);
printf("%s\n", s1);
return 0;
}
void squeeze(char s1[], char s2[])
{
int i, j, k;
k = 0;
for (i = 0; s1[i] != '\0'; ++i) {
for (j = 0; s2[j] != '\0'; ++j) {
if (s1[i] != s2[j])
s1[k++] = s1[i];
}
}
s1[k] = '\0';
}
When I run this code, terminal always gives Segmentation fault: 11.
Could anyone please give me any hints why this happens?

Example:
#include <stdio.h>
static int found(char *str, char c) { // return 1 if c is found in str
for (size_t i = 0; str[i] != '\0'; i++) {
if (str[i] == c) {
return 1;
}
}
return 0;
}
static void squeeze(char *a, char *b) {
size_t k = 0;
for (size_t i = 0; a[i] != '\0'; i++) { // use size_t to iterate on a c-string
if (found(b, a[i]) != 1) {
a[k++] = a[i]; // copy only if a[i] is not in b
}
}
a[k] = '\0';
}
int main(void) {
char a[] = "HelloWorld"; // you should let auto size
char b[] = "ol"; // and separate declaration
squeeze(a, b);
printf("%s\n", a);
}

Problem with your code is s1[k++] = s1[i];
Try to use new array
See Following Code
#include<stdio.h>
char *squeeze(char s1[], char s2[]);
int main()
{
char s1[20] = "HelloWorld", s2[20] = "olH";
squeeze(s1, s2);
return 0;
}
char *squeeze(char s1[], char s2[])
{
int i, j, k;
k = 0;
char arr[100]; // new array
int flag = 0;
for (i = 0; s1[i] != '\0'; i++) {
flag = 0;
for (j = 0; s2[j] != '\0'; ++j) {
if (s1[i] == s2[j])
{
flag = 1;
break;
}
}
if (flag == 0)
{
arr[k++] = s1[i];
}
}
arr[k] = '\0';
printf("%s",arr);
}

Related

C function for maniplulating string

I have written this exercise which should remove any chars in the first argument string which appear in the second string. But the result is a segmentation fault for the arguments below. Can any one explain to me what am I missing?
#include <stdio.h>
void squeez(char s1[], char s2[])
{
int i, j, k, match;
while (s1[i] != '\0') {
match = 0;
for (k = 0; s2[k] != '\0'; ++k) {
if (s1[i] == s2[k]) {
match = 1;
break;
}
}
if (match) {
i++;
} else {
s1[j++] = s1[i++];
}
}
s1[j] = '\0';
}
int main()
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
squeez(s, x);
printf("%s %s", s, x);
return 0;
}
For starters the function should be declared the following way
char * squeez( char s1[], const char s2[] );
That is the second parameter should have the qualifier const because the string specified by this parameter is not changed in the function.
The function should follow the general convention of C standard string functions and return pointer to the result string.
Within the function variables i and j are not initialized and have indeterminate values. So even the first while loop
int i, j, k, match;
while (s1[i] != '\0') {
// ...
invokes undefined behavior.
Instead of the type int of these variables you should use the type size_t because the type int can be not large enough to store lengths of strings.
You should declare variables in minimum scopes where they are used.
Keeping your approach to the function definition it can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
char * squeez( char s1[], const char s2[] )
{
size_t i = 0, j = 0;
while ( s1[i] != '\0' )
{
int match = 0;
for ( size_t k = 0; !match && s2[k] != '\0'; ++k )
{
if ( s1[i] == s2[k] ) match = 1;
}
if ( !match ) s1[j++] = s1[i];
i++;
}
s1[j] = '\0';
return s1;
}
int main(void)
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
puts( squeez( s, x ) );
return 0;
}
The program output is
adk
Also as the variable i is not used outside the while loop then the while loop could be substituted for a for loop where the variable i will be declared. For example
char * squeez( char s1[], const char s2[] )
{
size_t j = 0;
for ( size_t i = 0; s1[i] != '\0'; i++ )
{
int match = 0;
for ( size_t k = 0; !match && s2[k] != '\0'; ++k )
{
if ( s1[i] == s2[k] ) match = 1;
}
if ( !match ) s1[j++] = s1[i];
}
s1[j] = '\0';
return s1;
}
I noticed that the i and j are not initialized. In fact, your code is workable without the problem that I put forward. This is the code I tried.
#include <stdio.h>
void squeez(char s1[], char s2[])
{
int index1 = 0, position = index1, index2 = 0;
int match = 0;
while (s1[index1] != '\0')
{
match = 0;
for (index2 = 0; s2[index2] != '\0'; index2++)
{
if (s1[index1] == s2[index2])
{
match = 1;
break;
}
}
if (match)
index1++;
else
s1[position++] = s1[index1++];
}
s1[position] = '\0';
}
int main()
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
squeez(s, x);
printf("%s %s", s, x);
return 0;
}

C exercise return information about first position

exercise in C:
write a function 'any' wchich returns information about position of first occurrence in s1 any lsign from s2. Return -1 when s1 doesnt includes signs from s2.
And my code is:
#include <stdio.h>
#include <stdlib.h>
int any(char s1[], char s2[]) {
int i, j;
int koniec;
for (i = 0; s2[i] != '\0'; i++) {
for (j = 0; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]) {
koniec = j;
}
else
{
koniec = -1;
}
}
}
return koniec;
}
int main()
{
char w1[] = "Dominik";
char w2[] = "zcki";
int wynik;
wynik = any(w1, w2);
printf("%d", wynik);
return 0;
}
but it returns: -1
but should 3
what is wrong?
Just return the position when you find it and do not keep looping:
int any(char s1[], char s2[]) {
int i, j;
for (i = 0; s1[i] != '\0'; i++) {
for (j = 0; s2[j] != '\0'; j++) {
if (s1[i] == s2[j]) {
return j;
}
}
}
return -1;
}
The if statement within the inner loop
if (s1[j] == s2[i]) {
koniec = j;
}
else
{
koniec = -1;
}
Does not make a sense because the value of the variable koniec will be overwritten in the last iterations of the both loops.
Moreover due to the order of the loops you are searching in fact a character from the string s2 in the string s1 while you need to find the first character in s1 that is present in s2.
The function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stddef.h>
ptrdiff_t any( const char *s1, const char *s2 )
{
ptrdiff_t pos = -1;
for ( const char *p1 = s1; pos == -1 && *p1; ++p1 )
{
const char *p2 = s2;
while ( *p2 && *p2 != *p1 ) ++ p2;
if ( *p2 ) pos = p1 - s1;
}
return pos;
}
int main(void)
{
char w1[] = "Dominik";
char w2[] = "zcki";
printf( "%td\n", any( w1, w2 ) );
return 0;
}
The program output is
3
Indeed the first character from w1 that is present in w2 is the character 'i'. Pay attention to that positions start from 0.
#include <stdio.h>
#include <stdlib.h>
int any(char *s1, char *s2)
{
int koniec=0;
int j=0;
for (int i = 0; s1[i]!='\0'; i++)
{j=0;
while(s1[i]!=s2[j]&&s2[j]!='\0')
{
j++;
}
if(s2[j]!='\0')
{
return j;
}
}
return -1;
}
int main()
{
char w1[] = "Dominik";
char w2[] = "zcki";
printf("%d\n", any(w1, w2));
return 0;
}

Selection of unique characters

Please, help with the code.
Requirement:
Write a function my_union that takes two strings and returns, without doubles, the characters that appear in either one of the strings.
Example:
Input: "zpadinton" && "paqefwtdjetyiytjneytjoeyjnejeyj"
Output: "zpadintoqefwjy"
My code:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
char *my_union(char *a, char *b) {
char *str;
// Algorithm for excluding nonunique characters from string a(given in
// parameters).
str[0] = a[0];
int k = 1;
str[k] = '\0';
for (int i = 1; a[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == a[i]) {
is = false;
break;
}
}
if (is) {
str[k] = a[i];
k++;
str[k] = '\0';
}
} // In this case we are excluding excess character 'n' from "zpadinton", so
// str is equal to "zpadinto".
// Algorithm for adding unique characters from array b(given in parameters)
// into str.
for (int i = 0; b[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == b[i]) {
is = false;
break;
}
}
if (is) {
strncat(str, &b[i], 1);
}
}
return str;
}
The first algorithm is almost identical with second, but it doesn't work(. Mb I messed up with memory, give some advice, pls.
If you mean, get the unique characters from two strings and store them into a new string, try this code ;
First, you must allocate a memory for str. In your code, str is not pointing allocated memory location, so you will probably get segmentation fault.
int contains(const char * str,char c)
{
for (int i = 0; i < strlen(str); ++i)
if(str[i] == c)
return 1;
return 0;
}
char * my_union(char *a, char*b)
{
char * res = (char*)malloc(sizeof(char)*(strlen(a) + strlen(b)));
int pushed = 0;
for (int i = 0; i < strlen(a); ++i)
{
if(!contains(res,a[i])){
res[pushed] = a[i];
pushed++;
}
}
for (int i = 0; i < strlen(b); ++i)
{
if(!contains(res,b[i])){
res[pushed] = b[i];
pushed++;
}
}
return res;
}
int main(int argc, char const *argv[])
{
char string1[9] = "abcdefgh";
char string2[9] = "abegzygj";
char * result = my_union(string1,string2);
printf("%s\n", result);
return 0;
}
Also, do not forget the free the return value of my_union after you done with it.

C - How to input and insert a string into an array of strings?

I want to insert string to the array until I type "ok". Why I am getting just "ok" and original array at the output?
int main(void)
{
char b[20];
char* str[10] = { "1","2" };
int i = 2;
while (1) {
gets(b);
if (strcmp(b, "ok") == 0) break;
str[i] = b;
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
return 0;
}
You need to allocate a string on each iteration:
int main(void)
{
char* b;
char* str[10] = { "1","2" };
int i = 2;
while (1) {
b = malloc(20);
gets(b);
if (strcmp(b, "ok") == 0) break;
str[i] = b;
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
// free allocated strings
while (i > 2)
free(str[--i]);
return 0;
}
They all point to b, which gets overwritten in each iteration.
You need to create a copy of the string when you assign it:
str[i] = strdup(b);
You also may consider using fgets instead of gets; however, you will need to remove the newline:
size_t size;
fgets(str, 20, stdin);
size = strlen(str);
if(str[size-1] == '\n')
str[size-1] = '\0';
Also, print a newline at the end of your program, so it won't interfere with the shell:
putchar('\n');
Full code:
int main(void)
{
char b[20];
char* str[10] = { "1","2" };
int i = 2;
while (1) {
size_t size;
fgets(str, 20, stdin);
size = strlen(str);
if(str[size-1] == '\n')
str[size-1] = '\0';
if (strcmp(b, "ok") == 0)
break;
str[i] = strdup(b);
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
putchar('\n');
return 0;
}
You need to make a copy of the input string, then save a pointer to the copy of the input string in your array. Something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char b[20];
char *str[10] = { "1","2" };
int i = 2;
char *p;
size_t lenb;
for(i = 2 ; i < 10 ; ++i)
{
fgets(b, sizeof(b), stdin);
lenb = strlen(b);
if(lenb > 0 && *(b+lenb-1) == '\n')
{
*(b+lenb-1) = '\0'; /* overwrite the trailing \n */
lenb = strlen(b);
}
if (strcmp(b, "ok") == 0)
break;
p = malloc(lenb+1);
strcpy(p, b);
str[i] = p;
}
for (int j = 0; j < i; j++)
printf("%s\n", str[j]);
return 0;
}

Trying to compare two strings

It is sufficient to say that I am new to C so please have show some mercy ;).
I'm trying to compare two strings. The output shouldn't contain common characters. Sadly it does.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char msg[15] = "blueberry";
int c;
int s[15];
int j = 0;
int i = 0;
int k= 0;
int ok = 0;
int t = 0;
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
for (t=j=0; t < 15; ++t)
{
ok = 1;
//printf ("%c", s[t]);
}
for (k=0; msg[k] != '\0'; ++k)
{
if (s[t] == msg[k])
{
ok = 0;
}
}
if (ok == 1)
{
s[j] = s[t];
j++;
}
s[j] = '\0';
for (j = 0; j < 15; ++j)
printf ("%c ", s[j]);
}
The input from the keyboard is blackberry, expected output should've been U but sadly it is not. Any help please. Also why is it entering the nested for loop irrespective of condition?
My big thanks to everyone, it helped me a lot. I've figured out a way & am ok with the output. I've borrowed some ideas from A4L :).
To compare two string, you can use strcmp().
The following is a string compare program that you can use for your reference. I has both array and pointer version for better understanding.
#include <stdio.h>
int strcmp1(char a[], char b[])
{
int i=0;
while (a[i] == b[i]) {
if (a[i] == '\0')
return 0;
i++;
}
return a[i]-b[i];
}
int strcmp2(char *a, char *b)
{
while (*a == *b) {
if (*a == '\0')
return 0;
a++; b++;
}
return *a-*b;
}
int main()
{
char s1[] = "test string1";
char s2[] = "test string";
char s3[] = "aaa";
char s4[] = "bbb";
printf("strcmp1(%s, %s) = %d \n", s1, s2, strcmp1(s1, s2));
printf("strcmp2(%s, %s) = %d \n", s3, s4, strcmp2(s3, s4));
return 0;
}
given that msg contains "blueberry" and s contains "blackberry" this should do it
for (int i=0; i < strlen(msg); i++) {
for (int j = 0; j < strlen(s); j++) {
if (msg[i] != s[j]) {
printf ("%c", msg[i]);
}
}
}
yes it's ugly (using the strlen in the for gives me the chills, but I'm still low on coffeine today ^^)
i guess you want to find the first letter where the input differs from message
here is your own code with some fixes
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char msg[15] = "blueberry";
int c;
char s[15];
int i = 0;
int k= 0;
int ok = 0;
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = (char) c;
++i;
}
// make sure to terminate the string after hitting enter
s[i] = '\0';
printf("input: %s\n", s);
printf("messg: %s\n", msg);
// run through both input and message with one counter
for (k=0; ok == 0 && msg[k] != '\0' && s[k] != '\0'; )
{
// if different chars stop
if (s[k] != msg[k]){
ok = 1;
} else {
// next char
k++;
}
}
if (ok == 1)
{
printf ("diff # index %d -> %c\n", k, msg[k]);
}
else
{
printf ("no diff\n");
}
return 0;
}
#include <stdio.h>
#include <string.h>
//Length to match
int comm(char* s1, char* s2){
int len = 0;
while(*s1 && *s2 && *s1++ == *s2++)
++len;
return len;
}
//commdiffcomm
/*
int commr(char* s1, char* s2){
int len = 0, limit;
int len1,len2;
len1 = strlen(s1);
len2 = strlen(s2);
limit = len1 > len2 ? len2 : len1;
s1 = s1 + len1;
s2 = s2 + len2;
while(limit-- && *--s1 == *--s2)
++len;
return len;
}
//bad
int diff(char* s1, char* s2, int* len1, int* len2){
int len, lenr, s1_len, s2_len, wk_max, i, j;
len = comm(s1, s2);
if(strcmp(s1, s2)==0){
*len1 = *len2 = 0;
return len;
}
lenr = commr(s1, s2);
*len1 = strlen(s1) - len - lenr;
*len2 = strlen(s2) - len - lenr;
return len;
}
*/
int diff(char* s1, char* s2, int* len1, int* len2){
int len, s1_len, s2_len, wk_max, i, j;
len = comm(s1, s2);
if(strcmp(s1, s2)==0){
*len1 = *len2 = 0;
return len;
}
s1_len = strlen(s1 + len + 1);
s2_len = strlen(s2 + len);
wk_max = 0;
for(i = 1; i < s1_len ; i++){
for(j = 0; j < s2_len; j++){
int com_len;
com_len = comm(s1 + len + i, s2 + len + j);
if(wk_max < com_len){
wk_max = com_len;
*len1 = i;
*len2 = j;
}
}
}
return len;
}
int main(){
char str1[16] = "blueberry";
char str2[16] = "blackberry";
char dif1[16] = "";
char dif2[16] = "";
int len0;//length of top to diff pos
int len1;
int len2;
len0 = diff(str1, str2, &len1, &len2);
strncpy(dif1, str1 + len0, len1);
strncpy(dif2, str2 + len0, len2);
if(len1 !=0 && len2 != 0){
printf("%s different %s at position %d length %d (\"%s\")\n", str1, str2, len0, len1, dif1);
printf("%s different %s at position %d length %d (\"%s\")\n", str2, str1, len0, len2, dif2);
} else {
printf("two string is same.");
}
return 0;
}
/*
blueberry different blackberry at position 2 length 2 ("ue")
blackberry different blueberry at position 2 length 3 ("ack")
*/
There are a few problems with the code as is:
You don't null-terminate your input string. Attempting to use it with c string functons would spell trouble. To fix that, change
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
to
while (i < 14 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
Your specification is unclear as to whether you want your program to print the letters unique to msg, or to both s and msg. (i.e, do you want msg-s or (msg ∪ s)-(msg ∩ s) Assuming the first, the important part of your program goes like this:
k=0;
for(i=0;i<strlen(msg);i++){
int exists = 0;
for(j=0;!exists && j<strlen(s);j++){
if(msg[j] == s[i])
exists = 1;
}
if(!exists)
msg[k++] = msg[i];
}
s[k] = '\0';
The inner loop checks if s contains the current character in msg. If it does, we don't do anything, but if it doesn't, we append it to the end of a sublist we're creating on top of the bits of msg we've already processed.
your code is a mess even after the rewrite - there are too many errors to describe in detail
/*
blackbery
b l u e b e r r y
. . a c k b e . .
result = non-equal
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char msg[15] = "blueberry";
int c, s[15], i,j,k, ok;
for (i=0; i < 15; i++) s[i] = 0;
for (i=0; i < 15 && (c = getchar()) != '\n'; i++) s[i] = c;
for (ok=1, k=0; msg[k] != '\0'; ++k)
if (s[k] != msg[k]) ok = 0; else s[k] = '.';
for (j = 0; j < 15; ++j) printf ("%c ", msg[j]);
printf("\n");
for (j = 0; j < 15; ++j) printf ("%c ", s[j]);
printf("\nresult = %s\n", ok ? "equal" : "non-equal");
}

Resources