I am getting segmentation fault for the code below. To compile I typed gcc -std=c99 -g alphacode.c. This is a problem I am solving from here, and I am not sure what the problem is.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int catchar(char a, char b) {
char a1[2];
a1[1] = a;
a1[0] = b;
return atoi(a1);
}
int processNumber(char *num) {
int size = strlen(num);
int p[size];
if (num[size-1] != 0)
p[size-1] = 1;
else
p[size-1] = 0;
int i;
for (i = size-2; i>=0; i--)
{
if (catchar(num[i], num[i-1]) > 26 ||
catchar(num[i] , num[i-1]) <1 || num[i] == 0)
p[i] = p[i-1];
else
p[i] = p[i-1] + p[i-2];
}
return p[0];
}
int main() {
int bytes_read;
int nbytes = 5000;
char *number;
bytes_read = getline (&number, &nbytes, stdin);
while (bytes_read != -1) {
int out = processNumber(number);
printf("%d\n", out);
bytes_read = getline (&number, &nbytes, stdin);
}
return 0;
}
int catchar(char a, char b) {
char a1[2];
a1[1] = a;
a1[0] = b;
return atoi(a1);
}
atoi() expects a string, and a string must have a '\0' terminator, without it - atoi() will just keep looking until it find '\0', and you might get garbage or segfault - if you are out of your allocated memory.
You should declare your array of size 3, and put '\0' at index 2.
String needs to be null(0) terminated, thus you need array of 3 ( [a][b][\0]).
int catchar(char a, char b)
{
char concat[3] = { a,b,NULL};
return atoi(concat);
}
Related
Given array of strings, its size and another 1 string, I need to return an array of strings, which these strings are < (lexicographically) from the given string. Also: return the length of the returned array using given pointer size_res.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** LowerSTR(char* arr[], int size_arr, char* str, int* size_res) {
size_t i, j;
char** barr = malloc(size_arr);
*size_res = 0;
------> printf("TEST"); <-----
for(i=0; i<size_arr; i++) {
for(j=0; j<strlen(str); j++) {
if (arr[i][j] == '\0' || (int)(arr[i][j]) < (int)(str[j])) {
barr[(*size_res)++] = arr[i];
break;
}
else if ((int)(arr[i][j]) == (int)(str[j])) {
continue;
}
else {
break;
}
}
}
if (*size_res == 0) return NULL;
return barr;
}
I tried to test my code with this main:
int main() {
int* len;
char* arr[] = {"hello", "hola"};
char** ans = LowerSTR(arr, 2, "bonjour", len);
printf("%d", *len);
return 0;
}
But the line above the test printf(highlighted with ----> <---- in the function) causes error: segmentation fault - I cannot understand why..
code with strcmp:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** LowerSTR(char* arr[], int size_arr, char* str, int* size_res) {
size_t i;
char** barr = malloc(size_arr);
*size_res = 0;
for(i=0; i<size_arr; i++) {
if (strcmp(arr[i], str) <= 0)
barr[(*size_res)++] = arr[i];
}
if (*size_res == 0) return NULL;
return barr;
}
Given two sorted strings, I need to merge these strings to one string, and make it sorted.
sort by the ASCII value. for example:
acdty, berz => abcdertyz
My code:
#include <stdio.h>
#include <stdlib.h>
char* PairSortedArrays(char a[], char b[]) {
char* c = (char*)malloc((sizeof(a) + sizeof(b)) * sizeof(char));
int i, aPos = 0, bPos = 0;
for (i = 0; i < sizeof(*c); i++) {
if ((int)(a[aPos]) <= (int)(b[bPos])) {
c[i] = a[aPos];
aPos++;
}
else {
c[i] = b[bPos];
bPos++;
}
}
return c;
}
int main()
{
printf("%s", PairSortedArrays("acdty", "berz"));
return 0;
}
The first problem is with sizeof(a). if I code: printf("%d", sizeof(a)); it prints 8, while I expect it to print 5.
The expression i < sizeof(*c) controling the for loop is the main culprit. The corrected version of your program could be: (I edited the code a bit)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* PairSortedArrays(const char a[], const char b[])
{
size_t i;
const size_t total_len = strlen(a)+strlen(b);
char *c = malloc(total_len + 1);
size_t aPos = 0, bPos = 0;
for (i = 0; i < total_len; i++) {
if (a[aPos] == '\0') {
strcpy(c + i, b + bPos);
break;
}
if (b[bPos] == '\0') {
strcpy(c + i, a + aPos);
break;
}
c[i] = a[aPos] < b[bPos] ? a[aPos++] : b[bPos++];
}
return c;
}
int main()
{
printf("%s\n", PairSortedArrays("acdty", "berz"));
printf("%s\n", PairSortedArrays("az", "ks"));
return 0;
}
The return value of malloc must be checked against NULL in a real program. Also there is a memory leak (easy to fix).
When working with strings in C, you will want to be using strlen() to see how long they are, not sizeof (which merely tells you what the size of a pointer is).
Also note that sizeof(char) is 1 by definition, so there's no need to say "* sizeof(char)" in your malloc
sizeof(a) will return the size of a pointer in this case which will be 8 bytes if you compile for 64 architecture.
you have to either pass the size of each string or loop the string characters until you reach the '\0' if the string is null-terminated.
You should consider using qsort:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare_chars(const void *p1, const void *p2)
{
return *(const char *)p1 - *(const char *)p2;
}
char *PairSortedArrays(char *a, char *b)
{
char *c = malloc(strlen(a)+strlen(b)+1);
strcpy(c, a);
strcat(c, b);
qsort(c, strlen(c), sizeof(char), compare_chars);
return c;
}
int main()
{
printf("%s", PairSortedArrays("acdty", "berz"));
return 0;
}
How can I merge character by character two strings of different sizes to the n-th element of A and m-th element of B. I can easily do it when they have the same size (assuming here n=m). But cannot figure out how to handle this exception.
My working zip code is as follows:
char * zip(char *A, char *B, int n)
{
char *C;
int i;
C = malloc((2*n) * sizeof *A);
for(i=0; i<n; i++) {
C[(2*i)]=A[i];
C[(2*i)+1]=B[i];
}
return C;
}
But instead to pass just int n, I would like to pass also int m where n is to merge the n first elements of A and the m first elements of B. Hence passing the following input to the new_zip(char *A, char *B, int n, int m). A="rslxyzkw"; B="eutingxyz";n=3; m=6, I would get "resulting".
like this:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *new_zip(char *A, char *B, int n, int m){
assert(A != NULL && B != NULL && n >= 0 && m >= 0);
char *C = malloc(n + m + 1);//+1 for NUL
if(!C){
perror("malloc:");
return NULL;
}
int i = 0;
while(n + m > 0){
if(n > 0 && *A){
C[i++] = *A++;
--n;
}
if(m > 0 && *B){
C[i++] = *B++;
--m;
}
}
C[i] = 0;
return C;
}
int main (void){
char *result = new_zip("rslxyzkw", "eutingxyz", 3, 6);
printf("'%s'\n", result);
free(result);
return 0;
}
Instead of looping until a certain length you can loop until you run out of characters. C strings have a null character at the end so after you allocate the memory you can loop as long as both aren't a null character. All you need to do then is only add non-null characters to your output string.
#include <stdio.h> /* printf */
#include <stdlib.h> /* malloc, free */
#include <string.h> /* strlen */
char *zip(char *a, char *b)
{
char *c = malloc( (strlen(a)+strlen(b)+1) * sizeof(char) ), *p = c;
if(c)
{
while(*a || *b) /* while either string has characters */
{
if(*a) *p++ = *a++; /* add a character from a if non-null */
if(*b) *p++ = *b++; /* add a character from b if non-null */
}
*p='\0'; /* finish the string with a null character */
}
return c;
}
int main()
{
char *a = "This is a string";
char *b = "This is another longer string";
char *c = zip(a,b);
if(c)
{
printf("zip(%s,%s) = %s\n",a,b,c);
free(c);
}
return 0;
}
The following could work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* zip(char* A, char* B) {
char *C;
int k = 0;
C = (char*)malloc(strlen(A)+strlen(B)+1);
while (*A != '\0' || *B != '\0') {
if (*A != '\0') {
C[k++] = *A;
++A;
}
if (*B != '\0') {
C[k++] = *B;
++B;
}
}
C[k] = '\0';
return C;
}
int main() {
char *A = "123456", *B = "abcd", *C;
C = zip(A, B);
puts(C);
return 0;
}
The below code would work in the following way:
First do alternate merging from strings s1 and s2 based on the minimum value of m and n.
The second part would take care of appending the remaining elements either from s1 or from s2.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* merge (char *s1, char *s2, int m, int n)
{
char *s = (char *) malloc(m + n + 1);
int min = (m < n)? m: n;
int i = 0, j = 0, k = 0;
int count = 0;
/* Alternate merge from s1 and s2 to s*/
while (count < 2 * min) {
if (count % 2 == 0) {
s[k++] = s1[i++];
} else {
s[k++] = s2[j++];
}
count++;
}
/* Append the remaining elements from s1 or s2 to s*/
if (m > min) {
for (count = 0; count < m - min; count++) {
s[k++] = s1[i++];
}
} else if (n > min) {
for (count = 0; count < n - min; count++) {
s[k++] = s2[j++];
}
}
s[k++] = '\0';
return s;
}
int main()
{
char *s1 = "rslxyzkw";
char *s2 = "eutingxyz";
char *s = merge(s1, s2, 3, 6);
printf ("%s\n", s);
}
I am having trouble making an array equal another array in c.
in the main method it will not let me assign inputInt1 to the returned value of converTwosComp.
#include <stdio.h>
#include <stdlib.h>
int validChecker(char *input_StringIn);
int* convertTwosComp(char *inputStringIn, int *inputIntIn);
int main(void) {
char inputString1[11];
char inputString2[11];
int inputInt1[11];
int inputInt2[11];
printf(" is ");
inputInt1 = convertTwosComp(inputString1, inputInt1);
for(i = 0; inputString1[i]; i++){
printf("%d", inputInt1[i]);
}
int * convertTwosComp(char *inputStringIn, int *inputIntIn){
int digit;
int i;
if((inputStringIn[0] == '+') ||(inputStringIn[0]) == '0'){
inputStringIn[0] = 0;
}
if(inputStringIn[0] == '-'){
inputStringIn[0] = 1;
}
for(i = 0; inputStringIn[i]; i++){
digit = inputStringIn[i] - '0';
inputStringIn[i] = digit;
}
for(i = 0; inputIntIn[i]; i++){
if(inputIntIn[i] == 0){
inputIntIn[i] = 1;
}
if(inputIntIn[i] == 1){
inputIntIn[i] = 0;
}
}
return inputIntIn;
}
in the main method it will not let me assign inputInt1 to the returned value of converTwosComp.
This is what you probably need:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char array1[] = "Michi";
size_t len = strlen(array1);
char *array2 = malloc(len+1);
memcpy(array2, array1, len+1);
printf("Array2 = %s\n",array2);
free(array2);
return 0;
}
Output:
Array2 = Michi
You can always use a for loop to copy a string, in case you do not want to use memcpy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char one[30];
char two[30];
while(fgets(one,sizeof(one),stdin))
{
int len = strlen(one);
for(int i = 0; i < (len + 1); i++)
{
two[i] = one[i];
}
printf("%s", two);
break;
}
return EXIT_SUCCESS;
}
I am trying to search particular element in an array and copying to other.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
unsigned char a[16] = "1011\n23578A23\n\r";
unsigned char b[9];
unsigned char c[5];
unsigned char d[5] = "1011";
int i = 4;
memcpy(c,a,4);
printf("%s\n", c);
if(strcmp(c,d) == 0)
{
printf("\nEnter\n");
while(a[i] != '\r')
{
if(a[i] == '\n')
{
i = i+1;
printf("start copying\n");
memcpy(b,&a[i],8);
}
i = i+8;
}
}
}
But i am getting seg fault. Is my idea of increment is wrong?
You have to set the null terminator in c string.
memcpy(c,a,3);
c[4] = 0;
printf("%s\n", c);
#include <stdio.h>
#include <string.h>
int main(){
unsigned char a[16] = "1011\n23578A23\n\r";
unsigned char b[9] = {0};
unsigned char c[5] = {0};
unsigned char d[5] = "1011";
int i = 4;
memcpy(c,a,4);
printf("%s\n", c);
if(strcmp(c,d) == 0){
printf("\nEnter\n");
if(a[i] == '\n'){
i = i + 1;
printf("start copying\n");
memcpy(b, &a[i],8);
//printf("%s\n", b);
//i = i + 8;
}
}
}