Hi I am pretty new to C and was wondering how to return an entire array. For example I have this function here.
char* foo(int x)
{
char *num = (char*)malloc(x*sizeof(int));
num[0] = '1';
num[1] = '2';
num[2] = '3';
num[3] = '4';
return num;
}
I realized that when I return num it only returns the first index of num. But is there any way to return the whole array, 1234? Any help will be greatly appreciated!
Since the foo() function returns a pointer, you can see that all values are printed when you use the %s format specifier. The display() function prints the data in the memory area pointed to by the pointer as characters.
#include <stdio.h>
#include <stdlib.h>
char* foo(int x)
{
char* num = (char*) malloc((x + 1) * sizeof(char));
for(size_t i = 0 ; i < x ; ++i)
num[i] = i + 1 + '0';
num[x] = '\0';
return num;
}
void display(char *array, size_t size)
{
for(size_t i = 0 ; i < size && array[i] != '\0' ; ++i)
printf("array[%ld]: %c\n", i, array[i]);
}
int main()
{
const size_t size = 4;
char *result = foo(size);
printf("%s\n", result);
display(result, size);
return 0;
}
Output:
1234
array[0]: 1
array[1]: 2
array[2]: 3
array[3]: 4
See if you are new to C, then learn it first do some googling and research. If you don't find anything then read some theory of a similar topic for examples (How to return an array in C?). After that some error is happening in your code then you can ask it on stackoverflow.
By the way your should be like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *foo(int x); // fix prototype errors
char *foo(int x)
{
char *num = (char *)calloc(x + 1, sizeof(char)); // we added +1 to append the null terminating character in `num`
for (size_t i = 0; i < x; i++)
num[i] = (char)(i + 48);
return num;
}
/* #returns no. of character written on stdout */
int print_foo(const char *num); // fix prototype errors
int print_foo(const char *num)
{
if (num)
{
size_t z = 0;
for (size_t i = 0; i < num[i] != '\0'; i++)
z += fprintf(stdout, "num[%lu] = %c\n", i, num[i]);
return z;
}
return -1;
}
int main(void)
{
char *num = foo(10);
print_foo((const char *)num);
free(num); // free any heap allocated resources before exiting the application
return 0;
}
Related
I have done a code to solve the Sum String as Numbers problem on CodeWars.
On my machine it runs and returns the correct value, it also passes all tests on CodeWars, but for some reasons it's raised the Caught unexpected signal: 6 and free(): invalid pointer.
I have checked other questions related to this and other forums but it seems that i don't anything form there. I have used only size_t my pointer don't increase like a++ or anything in order to free to not be able to dealocate memory.
My code consists on:
a function char *to_num(const char *a,size_t *size) which converts all digits from ASCII to numbers (i.e. '3' => 3) and returns a char* to a dynamic allocated array with all that numbers. Also it removes all prefixed zeros.
void no_zeros(char *a) which simply deletes all the 0 from the start of a string (i.e. "0012" => "12")
a custom len function, because i use a different nul character, as my 0 in array is tehnically 0 digit. On this example i use 10 as terminating character
char *fill(char* a,size_t size) that returns a string prefixed with as many zeros as needed to reach the length size (i.e. for a="12" and size=4 it returns 0012)
and finnaly the main function char *strsum(const char *a, const char *b) which returns the sum written as a string (i.e. "123" + "456" returns "579")
The flow of this program goes like:
convert the strings received as parameter to numbers with to_num
if one number is longer than another the fill function is called to complet the smaller one so that we can perform the addition
than we perform the addition per components and return the number as string
I have a bug that prefixes my result with zero so i call the no_zeros on resut.
My code
#include <stdio.h>
#include <malloc.h>
#include <string.h>
void display(const char *a,size_t size){
for(size_t i=0;a[i]!=0 && i<size;i++){
if(a[i]>'0'){
printf("%c",a[i]);
}
else{
printf("%d",a[i]);
}
}
printf("\n");
}
char *to_num(const char *a,size_t *size){
size_t i=0,j=0;
*size = strlen(a);
char *result = malloc((*size+1)*sizeof(char));
if(result==NULL){return 0;}
while(a[i]=='0'){i++;}
while(a[i]!=0){
result[j] = a[i];
i++;
j++;
}
result[j]=0;
*size = j;
for(size_t i=0;i<*size;i++){
result[i] = result[i]-'0';
}
result[*size] =10;
return result;
}
void no_zeros(char *a){
size_t i=0,j=0;
while(a[i]=='0'){i++;}
while(a[i]!=0){
a[j] = a[i];
i++;
j++;
}
a[j]=0;
}
size_t len(char *a){
size_t s=0;
for(size_t i=0;a[i]!=10;i++){
s++;
}
return s;
}
char *fill(char* a,size_t size){
size_t a_size = len(a);
char *copy = malloc((size+2)*sizeof(char));
if(copy==NULL){return 0;}
for(size_t i=0;i<size-a_size;i++){
copy[i] = 0;
}
for(size_t i=0;i<a_size;i++){
copy[i+size-a_size] = a[i];
}
copy[size] = 0;
for(size_t i=0;i<size;i++){
}
return copy;
}
char *strsum(const char *a, const char *b)
{
size_t size_a,size_b,bigger,smaller;
char *x,*y;
x = to_num(a,&size_a);
y = to_num(b,&size_b);
bigger = size_a>=size_b ? size_a : size_b;
smaller = size_a<=size_b ? size_a : size_b;
if(bigger != smaller){
if(bigger == size_a){
y = fill(y,bigger);
size_b = bigger;
}
else{
x = fill(x,bigger);
size_a = bigger;
}
}
char *result = malloc((bigger+2)*sizeof(char));
if(result==NULL){return 0;}
int carry=0;
size_t i;
for(i=bigger;i>=0;i--){
result[i] = (x[i-1]+y[i-1]+carry)%10+'0';
carry = (x[i-1]+y[i-1]+carry)/10;
if(i==0) break;
}
result[bigger+1]=0;
no_zeros(result);
if(result[0]==0){return "0";}
free(x);
free(y);
return result;
}
int main(){
printf("%s\n",strsum("9567","800"));
}
display(): for(size_t i=0;a[i]!=0 && i<size;i++){: swap the order of the conditions so you do the boundary check before a[i].
strsum(): for(i=bigger;i>=0;i--){ doesn't make sense as i is a size_t i.e. unsigned and in the loop body you do x[i-1] and y[i-1] which is wrong when i is 0. What about this?
for(i=bigger; i; i--){
result[i] = (x[i-1]+y[i-1]+carry)%10+'0';
carry = (x[i-1]+y[i-1]+carry)/10;
}
result[0] = carry + '0';
strsum(): x and y leak as you free them after a return:
free(x);
free(y);
if(result[0]==0){return "0";}
strsum(): to_num() allocates an array and then fill() allocates a copy (2 mallocs) and in strsum() you may leak the first malloc() for either x or y:
x = to_num(a,&size_a);
y = to_num(b,&size_b);
// ...
if(bigger != smaller){
if(bigger == size_a){
y = fill(y,bigger);
size_b = bigger;
}
else{
x = fill(x,bigger);
size_a = bigger;
}
}
Either realloc() in fill() instead of creating a copy or use a temporary variable in strsum() so you can free the original malloc'ed value:
if(bigger != smaller){
if(bigger == size_a){
char *tmp = fill(y, bigger);
free(y);
y = tmp;
size_b = bigger;
}
else{
char *tmp = fill(x, bigger);
free(x);
x = tmp;
size_a = bigger;
}
}
Btw, this is the same code in both branches so consider writing a function.
main(): leaks the returned string:
int main(){
char *s = strsum("9567","800");
printf("%s\n", s);
free(s);
}
strsum(): Once you fix above mention leak in main() you can no longer do return "0". You would need a size check and possible realloc() before doing:
return strcpy(result, "0");
or you could free(result); return strdup("0");. This is most likely the root cause (in calling test code you don't see).
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;
}
I'm trying to write a function which will:
return :
0 if the strings have the same number of uppercase letters (A through Z)
-1 if s1 has more uppercase letters than s2
1 if s2 has more uppercase letters than s1
My biggest issue is the fact that strings aren't treated the same way in c as other languages which I have more experience in (java, python) I'm also a bit confused on when I should reference pointers/ dereference them. Here is my code:
#include <stdio.h>
#include <string.h>
int more_caps(char * s1, char * s2);
int main(int argc, char **argv){
int result = more_caps(argv[1], argv[2]);
printf("%d %s %s", result, argv[1], argv[2]);
return 0;
}
//EVERYTHING BEFORE THIS MUST NOT BE CHANGED------
int more_caps(char * s1, char *s2){
char * s1caps = strdup(s1);
char * s2caps = strdup(s2);
int *s1counter;
int *s2counter;
int i;
for(i = 0; i < sizeof(s1caps); i++){
int val1;
val1 = (int) *s1caps[i];
if (val1 > 65 && val1 <= 90){
*s1counter += 1;
}
}
for (i = 0; i < sizeof(s2caps); i ++ ){
int val2;
val2 = (int) *s2caps[i];
if (val2 > 65 && val2 <= 90){
*s2counter += 1;
}
}
if (*s1counter > *s2counter){
printf("\n");
return -1;
}
if (*s1counter < *s2counter){
printf("\n");
return 1;
}
else {
return 0;
}
}
I'm really confused on parsing through a char object and how i need to allocate memory or something. From reading the documentation, strdup(char) allocates the exact memory + 1 byte for the character i'm putting in the function? In anycase it's either seg faults or "indirection requires pointer operand". Any help? Thanks
No need to duplicate the strings nor use of magic numbers like 65. March down each string counting the occurrences of upper case letters using isupper()
#include <ctype.h>
int more_caps(char * s1, char *s2) {
unsigned up_count1 = 0;
// while pointer is not point to the terminating null character ...
while (*s1) {
if (isupper(*s1)) up_count1++;
s1++;
}
unsigned up_count2 = 0;
while (*s2) {
if (isupper(*s2)) up_count2++;
s2++;
}
// The compare/subtraction is idiomatic in C
// Each compare returns 0 or 1
return (up_count2 > up_count1) - (up_count2 < up_count1);
}
Some pedantic improvements for your later C education:
When using an index in C, or a count of elements in an array, the type size_t is preferred as it is the right size to index any array. Type int is sometimes too narrow.
size_t up_count1 = 0;
The is...() functions take int values in the range unsigned char and EOF. Casting to unsigned char is warranted here, but I doubt your test cases will expose the weakness of a non-casted usage.
if (isupper((unsigned char) *s1)) up_count1++;
#include <stdio.h>
#include <string.h>
int more_caps(char * s1, char * s2);
int main(int argc, char **argv){
int result = more_caps(argv[1], argv[2]);
printf("%d %s %s", result, argv[1], argv[2]);
return 0;
}
int more_caps(char * s1, char *s2){
//char * s1caps = strdup(s1);
//char * s2caps = strdup(s2);
int s1counter;
int s2counter;
s1counter = 0;
s2counter = 0;
int i;
for(i = 0; s1[i] != '\0'; i++){
int val1;
val1 = (int ) s1[i];
if (val1 > 65 && val1 <= 90){
s1counter += 1;
}
}
for (i = 0; s2[i] != '\0'; i ++ ){
int val2;
val2 = (int ) s2[i];
if (val2 > 65 && val2 <= 90){
s2counter += 1;
}
}
if (s1counter > s2counter){
printf("\n");
return -1;
}
if (s1counter < s2counter){
printf("\n");
return 1;
}
else {
return 0;
}
}
The fixed function which seems to work quite well. Thank you for the help.
I am trying to extends my Ruby code with a C functions. The C code compiles without warning. But When I try to run the ruby code, I got a segmentation fault:
I have this c code:
#include <ruby.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "nessie.h"
/* #define TRACE_INTERMEDIATE_VALUES */
/*
* The number of rounds of the internal dedicated block cipher.
*/
#define R 10
VALUE rb_mExample;
VALUE rb_cClass;
// ...
static char* displayHash(const unsigned char array[], int length){
int i, k;
char *str;
str = malloc(3 * length + 1);
if (str == NULL) {
return NULL;
}
k = 0;
str[0] = '\0';
for (i = 0; i < length; i++){
char hex[3];
if (i % 32 == 0){
str[k++] = ' ';
}
if (i % 8 == 0){
str[k++] = ' ';
}
snprintf(hex, sizeof(hex), "%02X", array[i]);
str[k++] = hex[0];
str[k++] = hex[1];
}
str[k] = '\0';
return str;
}
VALUE
print_string(VALUE class, VALUE *valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
int i;
for (i = 0; valor[i] != '\0'; i++);
int sizeo = i;
NESSIEinit(&w);
NESSIEadd((u8*)valor, 8*sizeo, &w);
NESSIEfinalize(&w, digest);
return (VALUE) displayHash(digest, DIGESTBYTES);
}
void
Init_example(){
rb_mExample = rb_define_module("Example");
rb_cClass = rb_define_class_under(rb_mExample, "Class", rb_cObject);
rb_define_method(rb_cClass, "print_string", print_string, 1);
}
and this Ruby code:
require "example"
def print
e = Example::Class.new
e.print_string("ruby")
end
When I run the ruby code, I got a segmentation fault.
EDIT: gist with log info
https://gist.github.com/psantos10/f07484afa26ce0e55181
Where I failing? I am new in C language.
EDIT:
I changed my "print_string" to look like this:
VALUE
print_string(VALUE class, VALUE *valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
int i;
for (i = 0; valor[i] != '\0'; i++);
int sizeo = i;
NESSIEinit(&w);
NESSIEadd((u8*)valor, 8*sizeo, &w);
NESSIEfinalize(&w, digest);
return rb_str_new(displayHash(digest, DIGESTBYTES), 128);
}
whith that, segmentation fault gone. But the string returned is coming with a strange characters like:
"ruby\x00\x00\x00\x00\x00No error detected.\x00\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD80x\xC0\x18`\x18\x18&F\xAF\x05#\x8C##\xB8\x91\xF9~\xC6?\xC6\xC6\xFB\xCDo\x13\xE8\x87\xE8\xE8\xCB\x13\xA1L\x87&\x87\x87\x11mb\xA9\xB8\xDA\xB8\xB8\t\x02\x05\b\x01\x04\x01\x01\r\x9EnBO!OO\x9Bl\xEE\xAD6\xD866\xFFQ\x04Y\xA6\xA2\xA6\xA6\f\xB9\xBD\xDE\xD2o\xD2"
When the correct must be only:
"ruby"
EDIT 3:
Making this change:
VALUE
print_string(VALUE class, VALUE *valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
/*
int i;
for (i = 0; valor[i] != '\0'; i++);
int sizeo = i;
*/
NESSIEinit(&w);
NESSIEadd((u8*)"ruby", 8*4, &w);
NESSIEfinalize(&w, digest);
return rb_str_new(displayHash(digest, DIGESTBYTES), 128);
}
the correct value are returned.
Then I try to to that:
VALUE
print_string(VALUE class, VALUE *valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
/*
int i;
for (i = 0; valor[i] != '\0'; i++);
int sizeo = i;
*/
NESSIEinit(&w);
NESSIEadd((u8*)"ruby", 8*4, &w);
NESSIEfinalize(&w, digest);
return rb_str_new2(valor);
}
Expecting "ruby" string to be returned. But not. It returns: "\x05"
What that mean?
for (i = 0; i < length; i++)
Inside this loop for each passing if condition you increment k so by doing this you will be having array out of bound access hence the crash.
Make sure the
char *str = malloc( 3 * length + 1);
is not
char *str = malloc( 3 * (length + 1));
For Eg:
Have value of length = 2;
char *str = malloc(7);
Now in the for loop you increment k 4 times.
k = 4;
Now after the second iteration if you exit the loop then
k=8;
So str[8] is not a valid access and might lead to crash
Before all, let me thanks #FrederickCheung for give me the right direction.
The solution code is:
VALUE
print_string(VALUE class, VALUE valor) {
struct NESSIEstruct w;
u8 digest[DIGESTBYTES];
VALUE info;
// Note here I must convert the Ruby VALUE type to C type. Thats is the trick.
char* valor2 = RSTRING_PTR(valor);
int i;
for (i = 0; valor2[i] != '\0'; i++);
int sizeo = i;
NESSIEinit(&w);
NESSIEadd((u8*)valor2, 8*sizeo, &w);
NESSIEfinalize(&w, digest);
info = rb_str_new_cstr(displayHash(digest, DIGESTBYTES));
return info;
}
For who want to see where this code was used, can access: https://github.com/AngoDev/kryptonita
I know that getline is C++ standard but I need to read a line of digits:
123856
and save it to an array. But how to do this without spaces between given (as input) digits? I want a user input to be:
123856 (with no spaces) and then save it to an array (n element array) and after that, I want my array to look like this:
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 8;
array[4] = 5;
array[5] = 6;
But how to make it in C, without a getline?
This is NOT what I want:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
int main(int argc, char **argv)
{
int t[4];
int i;
for(i=0; i<4; i++)
scanf("%d", &t[i]);
for(i=0; i<4; i++)
printf("%d\n", t[i]);
return 0;
}
If I understood you correct, the following should do it:
read the whole line
loop through the string as long as you get digits or the string ends
for every digit, place it's value in your array and increase the index by 1
while( ( c = getchar()) != EOF && c != '\n' && i < max ) {
/* If desired, add check for value outside of 0-9 */
array[ i++ ] = c - '0';
...
}
char arr[] = "1234567";
int intarr[10];
int count = 0;
for (char* ptr = arr; *ptr; ptr++) {
intarr[count] = *ptr - '0';
count++;
}
try this
#include <stdio.h>
#include <string.h>
main (int argc, char *argv[])
{
FILE *f;
int i=0;
int j=0;
char output[100];
char* output1[100];
char string[100];
char delims1[] = " ";
char delims2[] = "*";
char* result = NULL;
char* result3 = NULL;
int num;
//for (j=0; j<2; j++)
//{
//printf("%s",delims9[6]);
//}
f = fopen("text.txt","r");
//
while( fgets(string,sizeof(string),f) )
{
result = strtok( string, delims1 );
while( result != NULL )
{
output1[i]=result;
printf("%s\n",output1[i]);
result = strtok( NULL, delims1 );
i++;
}
for (num = 0; num < 100; i++ ) //
{ // Error On this array
printf("%s\n", output1[i]); //
} //
}
printf("\n%d",i/3+1);
return 0 ;
}
Ok, without using any string.
int digits = 123856;
int numofdigits = 1 + floor(log10(digits));
int digits_arr[numofdigits];
int i;
for(i = numofdigits-1; i >= 0; i--) {
digits_arr[i] = (int)floor(digits / pow(10, i)) % 10;
}
Try the below link... Same question asked here and get solution....
convert an integer number into an array
char * convertNumberIntoArray(unsigned int number) {
unsigned int length = (int)(log10((float)number)) + 1;
char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;
do {
*curr++ = number % 10;
number /= 10;
} while (number != 0);
return arr;
}