I've mulled over this for at least an hour and I still can't find out what the problem is.
#include <stdio.h>
typedef struct
{
int Level;
char* Name;
} Base;
Base baseStruct;
int main(int argc, char *argv[])
{
scanf("%s", baseStruct.Name);
scanf("%d", &baseStruct.Level);
printf("%s :: Level %d\n", baseStruct.Name, baseStruct.Level);
return 0;
}
What happens is, I go and enter the "Name" string, then when I type and enter the integer the program crashes. What is going on?
scanf("%s", ...)
This expects a buffer (scanf needs to write into it) and you give it an uninitialized pointer, that could point anywhere.
Consider doing one of the following:
Make Name a character buffer instead:
typedef struct
{
int Level;
char Name[100];
} Base;
Initialize it from the heap:
baseStruct.Name = malloc(100); /* do not forget to cleanup with `free()` */
You should also specify max string length in scanf format string to prevent overflow:
/* assume 'Name' is a buffer 100 characters long */
scanf("%99s", baseStruct.Name);
Don't feel bad everyone makes that mistake. The char * stands for a "pointer to a character" but the memory for the string itself is not allocated.
Add:
baseStruct.Name = malloc(sizeof(char)*100);
(note my syntax may be off a little)
Name is just an uninitialized pointer to a string. It doesn't point to anything useful. You'll need to initialize it properly to a string buffer. Also, you may want to limit the string through the formatting (like %100s) to make sure you don't overrun your buffer.
You haven't allocated any storage for Base.Name. You're scanning a string into a a pointer that doesn't point to any storage.
Allocate some space for the string. The problem is that you don't know how big a string will be copied in using scanf. Suppose you malloc 256 bytes and then scanf loads in a 300 byte string? Either allocate a string sufficiently large to handle all possible results from scanf, or modify your scanf to limit the characters, like:
baseStruct.Name = malloc(sizeof(char) * 256);
scanf("%256s", baseStruct.Name);
As others have pointed out, baseStruct.Name does not point to a valid memory region. However, allocating a fixed sized buffer is no safer. For a learning exercise, use
typedef struct
{
int Level;
char Name[1];
} Base;
and enter long strings to examine effects of buffer overflows.
For safe handling of input of indeterminate length, use fgets and sscanf or strtol (or strtoul if Base.Level cannot be negative.
Here is an example:
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INITIAL_BUFSIZE 100
#define MAX_BUFSIZE 30000
char *myreadline(FILE *fin) {
char *buffer;
int offset = 0;
int bufsize = INITIAL_BUFSIZE;
buffer = malloc(bufsize);
if ( !buffer ) {
return NULL;
}
while ( fgets(buffer + offset, bufsize, fin) ) {
size_t last = strlen(buffer) - 1;
if ( buffer[last] == (char) '\n' ) {
buffer[last] = 0;
break;
}
else {
char *tmp;
offset += bufsize - 1;
bufsize *= 2;
if ( bufsize > MAX_BUFSIZE ) {
break;
}
tmp = realloc(buffer, bufsize);
if ( !tmp ) {
break;
}
else {
buffer = tmp;
}
}
}
return buffer;
}
int myreadint(FILE *fin, int *i) {
long x;
char *endp;
char *line = myreadline(fin);
if ( !line ) {
return 0;
}
x = strtol(line, &endp, 10);
if ( (!*endp || isspace((unsigned char) *endp) )
&& (x >= INT_MIN) && (x <= INT_MAX ) ) {
*i = (int) x;
free(line);
return 1;
}
return 0;
}
typedef struct base_struct {
int Level;
char* Name;
} Base;
int main(int argc, char *argv[]) {
Base bs;
int i;
puts("Enter name:");
bs.Name = myreadline(stdin);
if ( !bs.Name ) {
fputs("Cannot read Name", stderr);
return EXIT_FAILURE;
}
puts("Enter level:");
if ( myreadint(stdin, &i) ) {
bs.Level = i;
printf("Name: %s\nLevel: %d\n", bs.Name, bs.Level);
free(bs.Name);
}
else {
fputs("Cannot read Level", stderr);
return EXIT_FAILURE;
}
return 0;
}
Output:
C:\Temp> t
Enter name:
A dark and mysterious dungeon
Enter level:
3456772
Name: A dark and mysterious dungeon
Level: 3456772
Related
I'm fairly new to C. I'm trying to read a .CSV file, then parse each line, then store the data in a dynamic array of pointers to structs. Unfortunately I've gone wrong somewhere in my implementation which is resulting in an infinite loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct dataSet {
char ID;
char postcode;
int population;
char contact;
double x;
double y;
}data;
int main(int argc, char* argv[]) {
char line[100] = "";
int count = 0;
int each = 0;
data *allData = NULL;
data *temp = NULL;
FILE *file = fopen("dataset.csv", "r");
if (file == NULL)
{
printf("Error! File null");
return 1;
}
while (fgets(line, sizeof line, file))
{
if(NULL == (temp = realloc(allData, sizeof(*allData) * (count + 1))))
{
fprintf(stderr, "realloc problem\n");
fclose(file);
free(allData);
return 0;
}
allData = temp;
if (6 == scanf(line, "%s, %s, %d, %s, %lf, %lf",
&allData[count].ID,
&allData[count].postcode,
&allData[count].population,
&allData[count].contact,
&allData[count].x,
&allData[count].y)) {
count++;
}
else {
printf("Problem with data\n");
}
}
fclose(file);
for (each = 0; each < count; each++)
{
printf("%s, %s, %d, %s, %lf, %lf\n",
&allData[count].ID,
&allData[count].postcode,
&allData[count].population,
&allData[count].contact,
&allData[count].x,
&allData[count].y);
}
free(allData);
return 0;
}
Any help or tips would be greatly appreciated.
[s]scanf() is a nasty function. You don't have enough control once it fails. Problem is: there are too many conditions: the input can be incorrect, or the destination is not large enough. Even reading complete lines with fgets(), and parsing them afterwards, will only allow you to skip complete lines; also: the line buffer is mostly fixed sized, and fgets() could read incomplete lines. A way to keep complete control is to read character-based. This might imply a Finite State machine.
A simpler reader (using a zero-state machine) could be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct omg {
char o;
int m;
char g[11];
};
struct wtf {
unsigned size;
unsigned used;
struct omg *array;
};
#define INITIAL_SIZE 7
struct wtf read_stuff(char *name)
{
FILE *fp;
unsigned icol,irec,len;
char buff[123];
struct wtf this = {0,0,NULL};
fp = fopen(name, "rb" );
if (!fp) return this;
for (icol=irec=len=0; ; ) {
int ch;
if (this.used >= this.size) {
size_t newsize;
struct omg *tmp;
newsize = this.size? this.size*2: INITIAL_SIZE;
fprintf(stderr, "Realloc(%zu)\n", newsize);
tmp = realloc(this.array, sizeof *this.array * newsize);
this.array = tmp;
this.size = newsize;
}
ch = getc(fp);
switch(ch) {
case '\r' : continue;
/* End of field or record: terminate buffer */
#if 0
case ',' :
#else
case '\t' :
#endif
case '\n' :
buff[len] = 0;
break;
case EOF :
goto done;
/* Normal character: assign to buffer
** You may want to report too long fields here
*/
default:
if (len >= sizeof buff -2) continue;
buff[len++] = ch;
continue;
}
/* When we arrive here, we have a new field. Let's process it ...*/
switch (icol) {
case 0: /* Assign first field here from buff[], (dont forget to check len!) */
this.array[this.used].o = buff[0];
break;
case 1: /* Assign second field from buff[], this may need some additional checks
** You may want to avoid sscanf() here ...
*/
sscanf(buff, "%d", &this.array[this.used].m );
break;
case 2: /* Assign third field from buff[] */
if (len >= sizeof this.array[this.used].g)
len = sizeof this.array[this.used].g -1;
memcpy (this.array[this.used].g, buff, len);
this.array[this.used].g[len] = 0;
break;
default: /* Ignore excess fields
** You may want to report hem.
*/
break;
}
/* Do some bookkeeping */
len = 0;
if(ch == '\n') {
/* You may want to check if icol==2, here */
icol=0; irec++; this.used++;
}
else icol++;
}
done:
fclose(fp);
/* You could do a final realloc() here */
return this;
}
int main(int argc, char **argv)
{
struct wtf result;
unsigned idx;
result = read_stuff(argv[1] );
fprintf(stderr, "Result=%u/%u\n", result.used,result.size);
for (idx=0; idx < result.used; idx++) {
printf("%c %d %s\n"
, result.array[idx].o
, result.array[idx].m
, result.array[idx].g);
if (idx >= 10) break;
}
return 0;
}
You ask for tips...
1 - your struct is wrong if your plan was to use dynamic memory. The char members should be pointers to char, ( char * not char ) as shown below. But to reduce complexity, use char arrays instead of forcing dynamic allocation for struct members: i.e. do not use this:
typedef struct dataSet {
char *ID;
char *postcode;
int population;
char *contact;
double x;
double y;
}data;
Rather use this:
typedef struct dataSet {
char ID[80];
char postcode[11];
int population;
char contact[80];
double x;
double y;
}data;
If the lengths are not right, then make them bigger, but this will reduce calls to calloc() and free().
2 - suggested steps:
Count lines in file. (example here). This will essentially open the file, count the lines and close the file.
Use the count to allocate memory for that number of instances of data (i.e. data *records = malloc(sizeof(*records)*countOfLines); )
Open the file again. If file != NULL, then...
Begin to read file line by line in a loop, such as the fgets(...) loop you have.
In this loop, suggest replacing scanf() with a series of calls to strtok() making the appropriate conversion one-by-one. Its a few more lines of code, but is easier in the long run to see what parsing problems you might run into.
The following pseudo code illustrates...
data *record = malloc(CountOfLines*sizeof(*record));
if(record)
{
int i = 0;
while(fgets(line, sizeof line, file))
{
tok = strtok(line, ",");
if(tok)
{ //convert string
strncpy(record[i].ID, tok, sizeof(record[i].ID) - 1);
tok = strtok(NULL, ",");
if(tok)
{//convert string
strncpy(record[i].postcode, tok, sizeof(record[i].postcode) - 1);
tok = strtok(NULL, ",");
if(tok)
{//convert int
record[i].population = atoi(tok);
//and so on ...
#include <string.h>
#include <stdlib.h>
int main() {
char getInput[20];
scanf("%s", getInput);
char append[] = "word";
printf("%s\n", strcat(append, getInput));
return 0;
}
Why does this give me illegal instruction 4
Prefer to use fgets into fixed buffer, and ensure that you leave room for null-terminator (and check that input not truncated).
Or, you can use scanf into fixed buffer, and you can use clever trick to ensure you do not overflow fixed buffer. Or you can use '%as' flag (if your compiler supports it).
Note that when you use dynamic allocation, you need to cleanup after yourself. This is why so many folks prefer garbage collected languages that perform memory cleanup/housekeeping for you.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char*
checkin(char* p) {
if( !p ) return(p);
if (0 == sizeof(p) ) {
printf("error: read empty!\n");
return NULL;
}
int plen = strlen(p);
if ('\n' != p[plen - 1]) {
printf("error: input overflow (too long)!\n");
return NULL;
}
return(p);
}
char*
wrap(char* p) {
char append[] = "word";
printf("%s%s\n",append,p);
char* combined = malloc(strlen(append)+strlen(p)+1);
strcpy(combined,append);
strcat(combined,p);
printf("%s\n",combined);
return(combined);
}
// use fixed size buffer, fgets
char*
getstuff() {
char line[666];
fgets(line, sizeof(line)-1, stdin);
if( NULL == checkin(line) ) return NULL;
char* combined = wrap(line);
return combined;
}
// use fixed size buffer, dynamic scanf
char*
getstuff2() {
char line[666];
// dynamically build scanf fmt to specify input width
char scanfmt[32];
sprintf(scanfmt,"%%%lds",sizeof(line));
scanf(scanfmt,line);
char* combined = wrap(line);
return(combined);
}
// use dynamic scanf read
char*
getstuff3() {
/* does your compiler support '%as' flag?
// use scanf to automagically malloc enough space
char *aline = NULL;
scanf("%as",&aline);
char* combined = wrap(aline);
free(aline);
return(combined);
*/
return(NULL);
}
int
main() {
char* stuff = getstuff();
if( NULL != stuff ) printf("got:%s\n",stuff);
free(stuff); stuff = NULL;
char* stuff2 = getstuff2();
if( NULL != stuff2 ) printf("got:%s\n",stuff2);
free(stuff2); stuff2 = NULL;
char* stuff3 = getstuff3();
if( NULL != stuff3 ) printf("got:%s\n",stuff3);
free(stuff3); stuff3 = NULL;
}
There are many ways to skin a cat, I prefer #37, crazy-glue and a toothbrush!
I would like to create an array of string variables, and the number of elements is depends on the user's input. For example, if the user's input is 3, then he can input 3 strings. Let's say "aaa", "bbb" and "ccc". They are stored by the same pointer to char(*ptr) but with different index.
code:
int main()
{
int t;
scanf("%d", &t);
getchar();
char *ptr = malloc(t*sizeof(char));
int i;
for(i=0;i<t;i++)
{
gets(*(ptr[i]));
}
for(i=0;i<t;i++)
{
puts(*(ptr[i]));
}
return 0;
}
t is the number of elements, *ptr is the pointer to array. I would like to store "aaa", "bbb" and "ccc" in ptr[0], ptr[1] and ptr[2]. However, errors have been found in gets and puts statement and i am not able to work out a solution. Would someone give a help to me? Thank you!
You shouldn't use gets(), which has unavoidable risk of buffer overrun, deprecated in C99 and deleted from C11.
Only one character can be stored in char. If the maximum length of strings to be inputted is fixed, you can allocate an array whose elements are arrays of char. Otherwise, you should use an array of char*.
Try this (this is for former case):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* the maximum length of strings to be read */
#define STRING_MAX 8
int main(void)
{
int t;
if (scanf("%d", &t) != 1)
{
fputs("read t error\n", stderr);
return 1;
}
getchar();
/* +2 for newline and terminating null-character */
char (*ptr)[STRING_MAX + 2] = malloc(t*sizeof(char[STRING_MAX + 2]));
if (ptr == NULL)
{
perror("malloc");
return 1;
}
int i;
for(i=0;i<t;i++)
{
if (fgets(ptr[i], sizeof(ptr[i]), stdin) == NULL)
{
fprintf(stderr, "read ptr[%d] error\n", i);
return 1;
}
/* remove newline character */
char *lf;
if ((lf = strchr(ptr[i], '\n')) != NULL) *lf = '\0';
}
for(i=0;i<t;i++)
{
puts(ptr[i]);
}
free(ptr);
return 0;
}
You can use this code which is given below because string array is like char 2D array so use can use pointer of pointer and when you allocate memory at run time by malloc then you need to cast into pointer to pointer char type.
int main()
{
int t;
scanf("%d", &t);
char **ptr = (char **)malloc(t*sizeof(char));
int i,j;
for( i=0;i<t;i++)
{
scanf("%s",ptr[i]);
}
for(i=0;i<t;i++)
{
puts(ptr[i]);
}
return 0;
}
Here is an example, of a clean if slightly memory inefficient way to handle this. A more memory efficient solution would use one string of MAX_LINE_LENGTH and copy to strings of precise lengths.. which is why one contiguous block of memory for the strings is a bad idea.
The asserts also just demonstrate where real checks are needed as malloc is allowed to fail in production where asserts do nothing.
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#define MAX_LINE_LENGTH 2048
int
main(void) {
int tot, i;
char **strheads; /* A pointer to the start of the char pointers */
if (scanf("%d\n", &tot) < 1)
return (1);
strheads = malloc(tot * sizeof (char *));
assert(strheads != NULL);
/* now we have our series of n pointers to chars,
but nowhere allocated to put the char strings themselves. */
for (i = 0; i < tot; i++) {
strheads[i] = malloc(sizeof (char *) * MAX_LINE_LENGTH);
assert(strheads[i] != NULL);
/* now we have a place to put the i'th string,
pointed to by pointer strheads[i] */
(void) fgets(strheads[i], MAX_LINE_LENGTH, stdin);
}
(void) printf("back at ya:\n");
for (i = 0; i < tot; i++) {
fputs(strheads[i], stdout);
free(strheads[i]); /* goodbye, i'th string */
}
free(strheads); /* goodbye, char pointers [0...tot] */
return (0);
}
So I'm trying to program a function which allows the user to enter an unlimited amount of chars. For example this:
char string[100]
limits the input to 100 characters.
The code i have so far is:
#include<stdio.h>
char* uinput(){
char *string, *current;
int counter = 0;
string = (char *) malloc(10 * sizeof(char));
do{
realloc(string, counter * sizeof(char));
current = string + counter;
*current = getchar();
counter++;
}while(*current != '\n');
return string;
}
int main(){
char *s;
s = uinput();
printf("\nYou entered: %s", *s);
return 0;
}
I'm new to pointers, so I'm not sure why this doesn't work(Program crashes). What I'm trying to do is keep reading a character and keep relocating the string pointer so the amount of bytes keeps increasing until the user presses enter ('\n').
Thanks
~Raf
Ok I think this is the problem
you are re-allocing
realloc(string, counter * sizeof(char));
The what will be the size of string in first iteration? It will be 0.
Now you are writing to a pointer which has 0 bytes allocated and hence segfault.
Changing it to a while loop can help to fix it. You can also change the initial value of counter to fix it
The approach is sane, but there are minor details that are wrong. If you compile with warnings enabled, you'd notice that you're missing <stdlib.h>; also you're giving the first character to printf instead of the pointer to the buffer.
Then there is the obvious bug that your size is reset to 0, and you're casting the return value of malloc, using char to store the result of getchar() which is also wrong because you cannot check against EOF. You're not saving the realloced pointer; and you're not terminating the string properly. On minor detail, you'd want to double the size of buffer in each realloc, because realloc needs to potentially copy the whole line, so it becomes slower and slower over time as the line grows in length.
Thus we get:
#include <stdio.h>
#include <stdlib.h>
char* uinput() {
char *string;
// number of characters in the buffer
size_t counter = 0;
// size of allocated buffer
size_t allocated = 16;
int c;
string = malloc(allocated); // sizeof(char) is 1
do {
c = getchar();
if (c == EOF) {
break;
}
// if our buffer is too small, double the allocation
if (counter + 2 <= allocated) {
size_t new_size = allocated * 2;
char *new_buffer = realloc(string, new_size);
if (! new_buffer) {
// out of memory? try smaller increment
new_size = allocated + 16;
new_buffer = realloc(string, new_size);
if (! new_buffer) {
// really out of memory: free old block
free(string);
return NULL;
}
}
allocated = new_size;
string = new_buffer;
}
// store the character
string[counter++] = c;
} while (c != '\n');
// terminate the buffer properly
string[counter - 1] = '\0';
return string;
}
int main() {
char *s = uinput();
if (!s) {
// possibly out of memory in uinput
perror("Error reading input");
exit(EXIT_FAILURE);
}
printf("\nYou entered: %s", s);
free(s);
return EXIT_SUCCESS;
}
You could try something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person{
char *name;
}pers;
void addMem(void);
int main(void){
addMem();
printf("\nYour name is:> %s\n",pers.name);
free(pers.name);
pers.name = NULL;
return 0;
}
void addMem(void){
unsigned int length = 6;
size_t newLength = 0;
unsigned int newSize = 0;
unsigned int i =0;
char *name;
int c;
name = malloc(length);
if(name == NULL){
exit(1);
}
newSize = length;
printf("Enter your name:> ");
while ((c = getchar()) != '\n' && c!=EOF){
name[i++]=(char)c;
if(i == newSize){
newSize = i+length;
name = realloc(name, newSize);
}
}
name[i] = '\0';
newLength = strlen(name)+1;
pers.name = malloc(newLength);
memcpy(pers.name, name, newLength);
free(name);
name = NULL;
}
Another approach is to use fgets(), which gets a string into a sized buffer from the input stream; if it has the complete input then the string ends with \n; if it doesn't then it doesn't. So you can loop calling fgets until there is an EOL character at the end, then depending on what your program does with the input you can decide whether to keep realloc-ing or to process the input a bit at a time.
use getchar, malloc and realloc for reading the unlimited input string
Declare String type, you can also use char *
// String type
typedef char *String;
I write this function for joining the char in the end of string
/**
* Join the Char into end of String
*
* #param string - String
* #param c - joined char
*/
void String_joinChar(String *string, const char c)
{
const size_t length = strlen(*string);
(*string) = (String)realloc((*string), sizeof(char) * (length + 2));
(*string)[length] = c;
(*string)[length + 1] = '\0';
}
This function for inputting string, which read the char from keyboard by using getchar and join it in the end of current string.
/**
* Input String
*
* #return Inputed String
*/
String String_input()
{
String string = (String)malloc(sizeof(char));
strcpy(string, "");
char cursor;
fflush(stdin);
while ((cursor = getchar()) != '\n' && cursor != EOF)
{
String_joinChar(&string, cursor);
}
return string;
}
Cause of using char *, malloc and realloc, we must free it
/**
* Destroy String
*
* #param string - Destroyed String
*/
void String_destroy(String string)
{
free(string);
}
And now we just use it !!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
String string = String_input();
printf("\n%s\n", string);
String_destroy(string);
return 0;
}
Hope useful to you!
I am trying to return a string from my sCopy() function, so I can print it in the main() function of my code. Please help.
const char *sCopy(char buffer[256], int i);
int main() {
int i;
int x;
char buffer[256];
char newBuffer;//[256];
printf("Please enter a number: ");
fgets(buffer, 256, stdin);
i = atoi(buffer);
printf("The value you entered is %d. Its double is %d.\n", i, i*2);
newBuffer = sCopy(buffer, i);
printf(newBuffer);
return 0;
}
const char *sCopy(char buffer[256], int i){
char nBuffer[256];
char *t;
int x;
for(x = 0; x < i; x++){
strcat(t, buffer);
}
//t = nBuffer;
return t;
}
My analysis below. From what I see here you should brush up on the difference between a pointer to char (char*) and a char array. I really appreciate though that you've tried to solve it yourself before asking.
const char *sCopy(char buffer[256], int i);
/* let's start from here, what i represents? Keep in mind that the most of the */
/* time an external developer will see just your declaration of a method, always */
/* try to give significant names to variables. */
int main() {
int i = 0;
/* always initialize variables to default values, especially if they are */
/* going to be indexes in a buffer. */
int x = 0;
char buffer[256] = "";
/* you can even initialize this to "" in order to mimic an empty string, */
/* that is a char array cointining just \0 (string null-terminator). */
char newBuffer[256] = "";
/* same here, you always need to declare the size of a char array unless */
/* you initialize it like this -char newBuffer[] = "hello"-, in which case */
/* the size will automatically be 6 (I'll let you discover/understand */
/* why 6 and not 5). */
printf("Please enter a number: ");
fgets(buffer, 256, stdin); // nice link at the bottom on input reading
i = atoi(buffer);
printf("The value you entered is %d. Its double is %d.\n", i, i*2);
newBuffer = sCopy(buffer, i);
printf(newBuffer);
return 0;
}
/* I am not going to debate the idea of returning a char pointer here :) */
/* Remember that in this case you are returning a pointer to some memory that has */
/* been allocated somewhere inside your function and needs to be released (freed) */
/* by someone outside your control. Are they going to remember it? Are they */
/* going to do it? In this case "they" is "you" of course. */
/* I'll let you explore alternative approaches. */
const char *sCopy(char buffer[256], int i){
char nBuffer[256] = ""; // see above
char *t = NULL;
/* you always init a pointer to NULL. As you can see, initializing here will */
/* make you think that there might be problem with the strcat below. */
int x; // ok here you can omit the init, but be aware of it.
for(x = 0; x < i; x++){
strcat(t, buffer);
/* what are you missing here? this piece of code is supposed to concatenate the */
/* input buffer to a brand new buffer, pointed by your variable t. In your implementation */
/* t is just a pointer, which is nothing more than a number to a memory location */
/* With the initialization, the memory location you are pointing to is NULL, which */
/* if de-referenced, will cause massive problems. */
/* What you are missing is the blank slate where to write your data, to which your */
/* pointer will read from. */
}
//t = nBuffer;
return t;
}
I really hope that this would help you. I am sorry but I can't write the solution just because I think it's better if you learn it the hard way. You can find plenty of tutorials of pointers to char and I am sure you will solve the problem.
(input reading) C scanf() and fgets() problem
Memory for char *t is not allocated. You can implement the string copy directly using strdup.
char *newBuffer = NULL;
...
...
newBuffer = strdup(buffer);
Try
char* newBuffer; // point to a c-string // here the return value of sCopy
and
static char nBuffer[256]; // make nBuffer survive beyond function call
and just use n return nBuffer, instead of t.
This is one way you could do it, without allocations. Alternatively allocate memory and return it instead of static char.
Try below:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void sCopy(char buffer[256], int i, char newBuffer[], int size)
{
char *t;
for(int x = 0; x < i; x++){
strcat(newBuffer, buffer);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int i;
char buffer[256] = {0};
char newBuffer[256] = {0};
printf("Please enter a number: ");
fgets(buffer, 256, stdin);
i = atoi(buffer);
printf("The value you entered is %d. Its double is %d.\n", i, i*2);
sCopy(buffer, i, newBuffer, 256);
printf("%s", newBuffer);
return 0;
}
Note that fgets appends a new line character at the end of the input string, so if you input 6 then the string is 0x36 0x0a where 0x36 is the ASCII code for 6 and 0x0a is the ASCII code for new line character, to remove this new line character, see this link
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *sCopy(char buffer[256], int i);
int main() {
int i;
int x;
char buffer[256];
const char* newBuffer;//[256];
printf("Please enter a number: ");
fgets(buffer, 256, stdin);
i = atoi(buffer);
printf("The value you entered is %d. Its double is %d.\n", i, i*2);
newBuffer = sCopy(buffer, i); //buffer tail '\n' need cut?
printf(newBuffer);
free(newBuffer);
return 0;
}
const char *sCopy(char buffer[256], int i){
char *t;
int x;
t=(char*)malloc(strlen(buffer)*i + 1);
*t='\0';
for(x = 0; x < i; x++){
strcat(t, buffer);
}
//t = nBuffer;
return (const char*)t;
}