Segmentation fault(core dumped) - cPointers [C] - c

I was assigned with a task of completing an assignment in C, without being taught C. (I have been learning Java) I am not sure how to fix this error nor do I know what the error means.
#include <stdio.h>
//int mystrcmp(char * s, char * t);
int main(int argc, char * argv[])
{
// #1 Prints out cmd line arguments
int i;
for (i = 0; i < argc; ++i)
{
printf("%s\n",argv[i]);
}
printf("\n"); //Spaceholder
// #2 String Compare
printf("%s %s\n", argv[1], argv[2]);
printf("Returned Value: %d\n", mystrcmp(argv[1], argv[2]));
//mystrcmp(argv[1],argv[2]);
// #3 String Concatenate
printf("\n"); //Spaceholder
printf("String Concatenate: %s\n", mystrcat(argv[1]));
// #4 String Copy
printf("\n"); //Spaceholder
// printf("String Copy: %s\n" , mystrcpy(argv[1]));
}
///////////
//Methods//
///////////
/* srtcmp: return < 0 if s < t, 0 if s==t, > 0 if s > t */
int mystrcmp(char * s, char * t)
{
int i;
for(i = 0; s[i] && s[2]; ++i)
{
if (s[i] == t[i] || (s[i]) == t[i])
continue;
else
break;
}
if (s[i] == t[i])
return 0;
if ((s[i]) < (t[i]))
return -1;
return 1;
}
mystrcat(char *dest, char *source)
{
int a = 0;
while(*(dest + a) != '\0')
{
a++;
}
int b = 0;
while(*(source + a) != '\0')
{
*(dest + a) = *(source + b);
a++;
b++;
}
}
mystrcpy(char * s, char * dest)
{
while((*s++ = *dest++)!= '\0')
;
return *dest;
}
I am assuming the error is coming from my mystrcat.

while(*(source + a) != '\0')
should be
while(*(source + b) != '\0')

Related

Why on while(getchar()!=EOF) it iterates extra time?

I'm trying to count chars from input, and I noticed that while(getchar()!=EOF) produces an extra count, Is it because it counts the null-terminated from input?
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define LINE 5
#define MEM_SIZE 10
char *getInput(int *counter);
void printInput(char *input);
int main() {
char *mainInput;
int counter = 0;
printf("Please enter your input:\n");
mainInput = getInput(&counter);
if (mainInput == NULL) {
return 1;
}
printf("\n\n\nOutput:\n%s\n", mainInput);
printf("number of chars: %d\n", counter);
printInput(mainInput);
free(mainInput);
return 0;
}
char *getInput(int *counter) {
char *p = (char *)malloc(MEM_SIZE * sizeof(char));
char *q = p; /* backup pointer, if realloc fails to allocate, function will return last address values stored */
int c;
int temp_counter = 0;
long current = 0, last = MEM_SIZE - 1;
while ((c = getchar()) != EOF) {
if (current >= last) {
q = p;
p = (char *)realloc(q, last + (MEM_SIZE * sizeof(char)));
if (p == NULL) {
printf("Memory allocation failed, printing only stored values \n");
return q;
}
last += MEM_SIZE;
}
p[current] = c;
temp_counter++;
printf("number of chars: %d\n", temp_counter);
++current;
}
p[current] = '\0';
(*counter) = temp_counter - 1;
return p;
}
void printInput(char *input) {
int i, j = 0;
while (input[j] != '\0') {
for (i = 0; i < LINE; i++) {
if (input[j] == '\0')
break;
putchar(input[j]);
++j;
}
if (input[j] != '\0')
putchar('\n');
}
}

Allocated Dynamically Array of pointers

i'm really stuck.
I pust a big part of code you can try to run it on in online c compiler. My problem is weird, every time after 2 iteration i lost the data on spliter[0][0] when i mean "lost" is modified, for better understand please look what is printing it.
Inside
Inside the loop that iterates I wanted to see if the characters were well allocated in the present time and this is the case, only afterwards when I want to check it is impossible for me to do anything.
My program boils down to separating one character string according to another and dynamically allocating these character strings in my split. Each separator character counts as separator.
I have already prepared the test in comment. I really need help, too long time im stuck here..
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int is_c(char c, char *cha) {
while (*cha) {
if (*cha == c) {
return (1);
}
cha++;
}
return (0);
}
int ct_str(char *str, char *cha) {
int sw;
int nbr;
char item;
nbr = 0;
while (*str) {
if (!(is_c(*str, cha)) && *str >= 33 && *str <= 127 && sw == 1) {
sw = 0;
nbr+=1;
}
str++;
while (is_c(*str, cha)) {
str++;
sw = 1;
}
}
return (nbr);
}
int no_blk(char *str, int position, char *cha) {
while (!is_c(str[position], cha)) {
if (str[position] >= 33 && str[position] <= 127)
return (1);
position++;
}
return (0);
}
int get_size(char *str, int position, char *cha) {
int item;
item = position;
int j;
j = 0;
while (str[item]) {
if (is_c(str[item], cha))
return (j);
item++;
j++;
}
return (0);
}
void split_this(char **split, char *str, char *cha) {
int i;
int level;
int sw;
int e;
level = 0;
i = 0;
int item = 0;
int element = 0;
while(str[i + 1]) {
e = 0;
while(is_c(str[i], cha)) {
sw = 1;
i++;
}
if(sw == 1 && (!is_c(str[i], cha)) && no_blk(str, i, cha)) {
split[level] = (char*)malloc(sizeof(char) * get_size(str, i, cha) + 1);
e = i;
//printf("%i \n", get_size(str, i, cha));
while(e - i < get_size(str, i, cha)) {
split[level][e - i] = str[e];
//printf("%c", split[level][e - i]);
split[level][(e + 1) - i] = '\0';
e++;
}
printf("%c", split[0][0]);
sw = 0;
level++;
}
i++;
}
free(split);
/*
int it = 0;
int ee;
while(split[it]) {
ee = 0;
while(split[it][ee]) {
printf("%c", split[it][ee]);
ee++;
}
it++;
}
*/
}
void ft_split(char *str, char *cha) {
char **spliter = NULL;
spliter = (char**)malloc(sizeof(char) * ct_str(str, cha) + 1);
split_this(spliter, str, cha);
}
int main(int argc, char **argv) {
//if (argc == 3)
//ft_split(argv[1], argv[2]);
ft_split("%%am%s%s%ss%%s%%%qsdqsd%%%on%vs%lre%" , "%%");
return (0);
}

Finding the needle in the Haystack using C

I'm having troubling figuring out why not my code is not iterating through the if statement until it finds the correct character.
#include <stddef.h>
#include <stdio.h>
char * my_strstr(char * param_1, char * param_2) {
int i;
int j;
for (i = 0; param_1[i] != '\0'; i++) {
printf("this is a loop for j %c\n", param_1[i]);
for (j = 0; param_2[j] != '\0'; j++) {
printf("this is a loop for j %c\n", param_2[j]);
if (param_1[i] == param_2[j]) {
printf("figuring out this %c\n", param_1[i]);
j++;
i++;
return &param_1[i];
printf("figuring out this %c\n", param_1[i]);
}
}
}
}
int main() {
char * param_1 = "hello";
char * param_2 = "ello";
printf("This is the string %s \n", my_strstr(param_1, param_2));
return 0;
}
I've pasted your code below with some edits and comments I hope will help.
#include <stddef.h>
#include <stdio.h>
char * my_strstr(char * param_1, char * param_2) {
int i;
int j;
for (i = 0; param_1[i] != '\0'; i++) {
// this should say "loop for i" shouldn't it?
printf("this is a loop for j %c\n", param_1[i]);
// use a flag to determine if you have found a match or not
int found = 1;
for (j = 0; param_2[j] != '\0'; j++) {
/* you actually want to compare param_1[i + j] == param_2[j] here
(respecting bounds of course). */
if (! param_1[i + j] || param_1[i + j] != param_2[j]) {
found = 0;
break;
}
printf("this is a loop for j %c\n", param_2[j]);
/* i don't understand what the following code was meant to do but you will
rarely want to increment i and j outside of the for ()
if (param_1[i] == param_2[j]) {
printf("figuring out this %c\n", param_1[i]);
j++;
i++;
return &param_1[i];
printf("figuring out this %c\n", param_1[i]);
}
*/
}
// here you want to check if you found it, and return if so.
if (found) {
return &param_1[i];
}
}
// need a default for if it is never found:
return NULL;
}
int main() {
char * param_1 = "hello";
char * param_2 = "ello";
printf("This is the string %s \n", my_strstr(param_1, param_2));
return 0;
}

Segmentation fault error while working with command-line argument, C program

I am working on a program that decodes a message provided as a morse code as a command line argument. If the provided string contains 7 spaces it means that I need to print a space to the decoded string. Currently, my program shows all correct letters, but I cannot overcome the issue with locating 7 spaces in a string and printing one space instead.
Here is the issue and how I pass the encoded string:
e3r2p2% ./morse "..- -.. .-. .. .-- --. ..- ....."
udriwg zsh: segmentation fault ./morse "..- -.. .-. .. .-- --. ..- ....."
Program works fine and prints all the decrypted letters (udriwg) till it meets the first (or maybe second) space out of 7;
Here is the code of my program:
int find_morse(const char *s);
bool count_spaces(char *s);
bool is_valid_char(char *s);
bool is_valid_params(int argc, char *argv[]);
void mx_printchar(char c);
void mx_printerr(const char *s);
int mx_strcmp(const char *first, const char *second);
char* mx_strcpy(char* dest, const char* source);
int mx_strlen(const char *s)
int main(int argc, char *argv[]){
if (!is_valid_params(argc, argv)){
mx_printerr("usage: ./morse \"str\"\n");
exit(1);
}
char *output[27]= {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
"p","q","r","s","t","u","v","w","x","y","z","."};
char *copy;
copy = malloc(mx_strlen(argv[1]) + 1);
if (copy != NULL) {
mx_strcpy(copy, argv[1]);
} else {
mx_printerr("usage: ./morse \"str\"\n");
exit(1);
}
int buff = 0;
char temp[5];
int index;
int space = 0;
int j;
for (int i = 0, n = mx_strlen(copy); i < n; i++) {
if (copy[i] == '.' && copy[i + 1] == '.' && copy[i + 2] == '.'
&& copy[i + 3] == '.' && copy[i + 4] == '.') {
mx_printchar(*output[26]);
}
if (copy[i] != ' ') {
temp[buff] = copy[i];
buff++;
}
if (copy[i] == ' ') {
index = find_morse(temp);
//print letter converted from morse to ENG
mx_printchar(*output[index]);
j = i;
while (copy[j] == ' ') {
space++;
j++;
if (space == 7) {
mx_printchar(' ');
space = 0;
break;
}
}
temp[buff] = '\0';
buff = 0;
for(int j = 0; j <4; j++) {
temp[j] ='\0';
}
}
}
mx_printchar('\n');
free(copy);
return 0;
}
int find_morse(const char *s) {
char *input[27]={".-","-...","-.-.","-..",".","..-.","--.", "....", "..",
".---","-.-",".-..","--","-.", "---",".--.","--.-",".-.",
"...","-","..-", "...-",".--","-..-","-.--","--..","....."};
for (int i = 0; i < 27; i++) {
if (mx_strcmp(s, input[i]) == 0) {
return i;
}
}
return -1;
}
bool count_spaces(char *s) {
int space = 0;
for (int i = 0; s[i] != '\0'; i++) {
if (s[i] == ' ') {
space++;
if (s[i + 1] != ' ') {
if (space != 1 && space != 7) {
return false;
} else {
space = 0;
}
}
}
}
return true;
}
bool is_valid_char(char *s){
int i = 0;
while (s[i] != '\0'){
if (s[i] != ' ' && s[i] != '-' && s[i] != '.') {
return false;
}
i++;
}
return true;
}
bool is_valid_params(int argc, char *argv[]){
if (argc != 2) {
return false;
}
if (!is_valid_char(argv[1])){
return false;
}
if (!count_spaces(argv[1])){
return false;
}
return true;
}
void mx_printchar(char c){
write(1, &c, 1);
}
void mx_printerr(const char *s){
write(2, s, mx_strlen(s));
}
int mx_strcmp(const char *first, const char *second) {
while (*first) {
if (*first != *second) break;
first++;
second++;
}
return *(const unsigned char*)first - *(const unsigned char*)second;
}
char* mx_strcpy(char* dest, const char* source){
if (dest == NULL) {
return NULL;
}
char *ptr = dest;
while (*source != '\0') {
*dest = *source;
dest++;
source++;
}
*dest = '\0';
return ptr;
}
int mx_strlen(const char *s){
int length = 0;
while (s[length] != '\0'){
length++;
}
return length;
}
I believe the issue starts here:
j = i;
while (copy[j] == ' ') {
space++;
j++;
if (space == 7) {
mx_printchar(' ');
space = 0;
break;
}
}
Program prints the decripted letter, then tries to check those spaces but somethis go wrong.
I'd appreciate any suggestions as how to resolve it
When using a program from command line you always put a space as a delimiter between your program name and the parameters and other parameters. So, in your case if there are 7 spaces then a extra space will be added as delimiter between your program name and 7 spaces making it to 8 spaces like this ./morse. So, I'd rather suggest to use any other symbol like ! or any other symbol.
Now for the Segmentation fault error I think that's not happening because of that space counter section that's happening because of this line copy = malloc(mx_strlen(argv[1]) + 1); as you must know that malloc() returns a void * to the allocated space.Now here I don't know what those mx_ functions are. Also some questions popped out in my mind while I was debugging your code those answers are included in the modified code(at somewhat satisfying level) i'm putting below. Please answer them in comments.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Questions
** 1. What are these mx_ functions?
** 2. What is is_valid_params?
** 3. Can't we define *output[27] as *output = "abcdef...z." ?
** 4. In " for(j = 0; j < 4; j++) temp[j] ='\0'; " why j < 4 instead of j < 5?
*/
// Function Prototype
int find_morse(const char *s);
//main()
int main(int argc, char *argv[])
{
char *output[27]= {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","."};
char *copy, temp[5];
int buff = 0, index, space = 0, i, j, n;
// Checking for valid parameters.
if (argc != 2)
{
printf("usage: ./morse \"Invalid Parameters.\"\n");//mx_printerr("usage: ./morse \"str\"\n");
exit(1);
}
copy = (char *)malloc(strlen(argv[1]) + 1);
if (copy != NULL)
strcpy(copy, argv[1]);
else
{
printf("usage: ./morse \"Memory Unavailable.\"\n");
exit(2);
}
for (i = 0, n = strlen(copy); i < n; i++)
{
if (copy[i] == '.' && copy[i + 1] == '.' && copy[i + 2] == '.' && copy[i + 3] == '.' && copy[i + 4] == '.')
putchar(*output[26]);
if (copy[i] != ' ')
temp[buff++] = copy[i];
else
{
j = i;
while (copy[j] == ' ')
{
space++;
j++;
if (space == 7)
{
putchar(' ');
space = 0;
break;
}
}
temp[buff] = '\0';
buff = 0;
// Emptying temp[5]
//for(j = 0; j < 5; j++)
temp[0] = '\0'; // Rest elements will automatically be assigned to \0 by compiler.
}
if(index = find_morse(temp) != -1)
putchar(*output[index]); //print letter converted from morse to ENG
}
putchar('\n');
free(copy);
return 0;
}
int find_morse(const char *s)
{
char *input[27] = {".-","-...","-.-.","-..",".","..-.","--.", "....", "..",".---","-.-",".-..","--","-.", "---",".--.","--.-",".-.","...","-","..-", "...-",".--","-..-","-.--","--..","....."};
for (int i = 0; i < 27; i++)
{
if (strcmp(s, input[i]) == 0)
return i;
}
return -1;
}
Here in this program I didn't understand that how the user will enter morse code one by one or as a string. Because, when matching those morse code entries, I'm sure a logical error would occur.

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