0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
  char dayofweek[] = "Friday";
  int day = 13;
  char month[] = "May";
  int year = 1927; 
  char *string; //I want to save my date into this string
  const size_t memory;


//trying to allocate memory
memory = malloc(strlen(dayofweek)+strlen(month)+intlen(day)+intlen(year));

//trying to write my strings and ints into one string
snprintf(string, memory, "%s der %d.%s %d\n", dayofweek, day, month, year);


printf("%s\n", string);


free(string);
return 0;
}

Hey guys, im completely new to programming, and i'm trying to find out how to save all my variables into one string, while allocating the needed memory. The trainingtask was to learn how to use the snprintf function. The "const size_t memory;" was also given, but i dont know where i have to use it.

hope you guys can help me, greetings!

manti13
  • 91
  • 3
  • 10
  • 1
    You're not allocating enough memory - you've forgotten to take into account there are spaces in your string and also that you need space for the NUL terminating character too. – Chris Turner Nov 07 '18 at 11:51
  • You have mixed up your variables: `memory` is an unsigned integer that should hold the number of bytes you need; `string` is a pointer to char that will be used as the handle to allocated memory,i.e. the return value of `malloc`. – M Oehm Nov 07 '18 at 11:54
  • Use [asprintf](http://man7.org/linux/man-pages/man3/asprintf.3.html). If you don't have it, get the memory _size_ of the string from `memory = snprintf(NULL, 0, ...`, see [this thread](https://stackoverflow.com/questions/3774417/sprintf-with-automatic-memory-allocation). – KamilCuk Nov 07 '18 at 12:33
  • `memory = malloc(...` This will not even compile cleanly. Did you actually read the compiler warnings? – Lundin Nov 07 '18 at 14:40

3 Answers3

1

Aside from not allocating enough memory, you've confused what size_t is for - it's for storing the size of things, not for storing memory. So you want to store the amount of memory you want to allocate in memory. And store the results of malloc in string.

So you want something like this. The extra 8 is for the spaces and other characters in your output and the NUL terminating character.

memory = strlen(dayofweek)+strlen(month)+intlen(day)+intlen(year)+8;
string = malloc(memory);

Or if you don't write yourself intlen

memory = strlen(dayofweek)+strlen(month)+14;
Chris Turner
  • 8,082
  • 1
  • 14
  • 18
  • thanks for the answer. I always get an error, that intlen is invalid, but strlen is working, do you know what else can i use for that. I've used your code now and it says: caanot assign to variable "memory" with const_qualified type const size_t (aka const unsigend long) – manti13 Nov 07 '18 at 12:19
  • This is just pseudocode. It is expected that You to remove the `const` from `memory` variable declaration, also it is expected that you write `intlen` function which returns the length of representation of an number in a decimal system (base 10). – KamilCuk Nov 07 '18 at 12:27
  • sorry for asking, im completely new to this. How can i make such a intlen function. Something like int intlen = length of int? – manti13 Nov 07 '18 at 12:51
  • I assumed you'd written `intlen` already, but not included it. You could forget about using `intlen()` entirely since you know that the day will be at most 2 digits and year would be 4 (at least for the next 8000ish years). – Chris Turner Nov 07 '18 at 13:01
  • so i can just go for (strlen(dayofweek)+strlen(monat)+14) 14 bcause of 8 for spaces etc 4 for year and 2 for day, right? – manti13 Nov 07 '18 at 13:09
  • Sure. You could even go further and use the length of the longest month and dayofweek too instead of `strlen()`- it depends on whether your task requires you to allocate the exact amount of memory required or not. – Chris Turner Nov 07 '18 at 13:18
  • Off by 1. Review `8`. I'd suggest `define FMT "%s der %d.%s %d\n" memory = malloc(strlen(dayofweek)+strlen(month)+intlen(day)+intlen(year) + sizeof FMT): snprintf(string, memory, FMT, dayofweek, day, month, year);` and not worry about slightly over allocating. Avoid magic numbers. – chux - Reinstate Monica Nov 07 '18 at 13:19
  • so chris, i dont know how to write code in the comments section, but it seems to work now. Sadly it is ignoring my memory allocation. I have declared "size_t memory;" and under that i wrote "memory = (strlen(dayofweek)+strlen(month)+14); string=malloc(memory);" if i change my number at the end to f.e. +7 it is still printing out everything just fine, so it is ignoring my malloc. – manti13 Nov 07 '18 at 13:19
  • if it is working, it can't be ignoring your memory allocation - it's the 2nd parameter to `snprintf` that limits how much is added to `string` - if you set it to less than enough it should truncate it – Chris Turner Nov 07 '18 at 13:26
  • whoops, was using sprintf, now everything works perfectly. Thank you very much chris! – manti13 Nov 07 '18 at 13:40
  • Use of magic numbers twice here 8 and 14 resulted in insufficient memory allocation and demonstrates how easily manual calculations can be wrong. Should have been at least 9,15. OP may not see this as `printf("%s\n", string);` lacks sentinels to show the the `'\n'` from the format was not written. – chux - Reinstate Monica Nov 07 '18 at 13:56
1

how to store them all in one string and how to allocate dynamic memory to it?

Call snprintf() twice. First to determine memory needs. @Kamil Cuk

The snprintf function returns the number of characters that would have been written had n been sufficiently large, not counting the terminating null character, or a negative value if an encoding error occurred. C11 §7.21.6.5 3

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
  char dayofweek[] = "Friday";
  int day = 13;
  char month[] = "May";
  int year = 1927; 

  int len = snprintf(NULL, 0, "%s der %d.%s %d\n", dayofweek, day, month, year);
  size_t memory = len + 1u;
  char *string = malloc(memory);
  len = snprintf(string, memory, "%s der %d.%s %d\n", dayofweek, day, month, year);

  printf("<%s>\n", string);

  free(string);
  return 0;
}

Pedantic code would add checks to insure len >= 0 (2 places) and if allocation succeeded.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

As far as I know you C does not have intlen() function , at least not in the header files which you include your project. strlen() returns the length of string but for others, you have to decide the needed amount of space for char by your self. Beside of this to able to use pointer you need to specify a memory block; otherwise you cannot use pointer like the definition of yours char*string.To explain myself I attached two piece of code please check

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int intlen(int data4_allocate) {
 return floor(log10(abs(data4_allocate))) + 1;
}
int main() {

    char dayofweek[] = "Friday";
    int day = 13;
    char month[] = "May";
    int year = 1927;
    char *string; //I want to save my date into this string
    const size_t *memory;
    //trying to allocate memory
    memory = (size_t*)malloc(strlen(dayofweek) + strlen(month) + intlen(day) + 
    intlen(year));
    string = (char*)malloc(sizeof(memory)+1);
    //trying to write my strings and ints into one string
    snprintf(string, (size_t)memory, "%s der %d.%s %d\n", dayofweek, day, month, 
    year);

    printf("%s\n", string);

   free((char*)string);
   return 0;
}

or you can define a macro which determines the maximum byte length of given numbers in that case your code might be like following code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main() {
    #define MONTH_BYTE_SIZE 2 // 0 -- 12  max 2 char needed 
    #define DAY_BYTE_SIZE 2 // 0-31 max 2 char needed
    #define YEAR_BYTE_SIZE 4 // 0--2999 max 4 char needed 

    char dayofweek[] = "Friday";
    int day = 13;
    char month[] = "May";
    int year = 1927;
    char *string; //I want to save my date into this string
    const size_t *memory;

   //trying to allocate memory
   memory = (size_t*)malloc(strlen(dayofweek) + (sizeof(char)*MONTH_BYTE_SIZE) + 
   (sizeof(char) * DAY_BYTE_SIZE) + (sizeof(char) * YEAR_BYTE_SIZE));
   string = (char*)malloc(sizeof(memory)+1);
   //trying to write my strings and ints into one string
   snprintf(string, (size_t)memory, "%s der %d.%s %d\n", dayofweek, day, month, 
   year);
   printf("%s\n", string);
   free((char*)string);
   return 0;

}

the result should be like

this

Cagri Candan
  • 90
  • 1
  • 9
  • @ManuelTietz This code has problems. `size_t *memory` is a pointer assign spaced with `memory = (size_t*)malloc(...)`. It should be an integer. What is needed here is `size_t memory = strlen(dayofweek) + (sizeof(char)*MONTH_BYTE_SIZE) + (sizeof(char) * DAY_BYTE_SIZE) + (sizeof(char) * YEAR_BYTE_SIZE + some_more;` If code works, it is due to _undefined behavior_. – chux - Reinstate Monica Nov 07 '18 at 19:54