I'm trying to create a string with n characters by allocating memories with malloc, but I have a problem - string

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
printf("Length? ");
scanf("%d", &n);
getchar();
char* str = (char*)malloc(sizeof(char) * (n+1));
fgets(str,sizeof(str),stdin);
for (int i = 0; i < n; i++)
printf("%c\n", str[i]);
free(str);
}
Process results like this!
Length? 5
abcde
a
b
c
?
(I wanted to upload the result image, but I got rejected since I didn't have 10 reputations)
I can't figure out why 'd' and 'e' won't be showing in the results.
What is the problem with my code??

(wellcome to stackoverflow :) (update #1)
str is a pointer to char instead of a character array therefore sizeof(str) is always 8 on 64-bit or 4 on 32-bit machines, no matter how much space you have allocated.
Demo (compilation succeeds only if X in static_assert(X) holds):
#include <assert.h>
#include <stdlib.h>
int main(void){
// Pointer to char
char *str=(char*)malloc(1024);
#if defined _WIN64 || defined __x86_64__ || defined _____LP64_____
static_assert(sizeof(str)==8);
#else
static_assert(sizeof(str)==4);
#endif
free(str);
// Character array
char arr[1024];
static_assert(sizeof(arr)==1024);
return 0;
}
fgets(char *str, int num, FILE *stream) reads until (num-1) characters have been read
Instead of fgets(str,sizeof(str),stdin) please fgets(str,n+1,stdin)
Fixed version:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(void){
int n=0;
printf("Length? ");
scanf("%d",&n);
getchar();
char *str=(char*)calloc((n+1),sizeof(char));
static_assert(
sizeof(str)==sizeof(char*) && (
sizeof(str)==4 || // 32-bit machine
sizeof(str)==8 // 64-bit machine
)
);
fgets(str,n+1,stdin);
for(int i=0;i<n;++i)
printf("%c\n",str[i]);
free(str);
str=NULL;
}
Length? 5
abcde
a
b
c
d
e

Related

Wrong output with scanf function

so this is supposedly not a difficult question, but I've been getting this problem a few times when running my code in VS code. I am trying to separate the alphabets and numbers from the string, and I have used the method as follows (in my code) according to what is taught in the book. However, despite having the program running, the output is wrong.
Here is my code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int main(){
int weight = 0;
int height = 0;
char wunit[] = "";
char hunit[] = "";
printf("Enter the body weight: ");
scanf("%d%s",&weight,wunit);
printf("Enter the height: ");
scanf("%d%s",&height,hunit);
printf("%d,%s,%d,%s", weight, wunit, height, hunit);
return 0;
}
The thing is,if I type in 20lb for weight, and 30mt for height, what happens is that it gives the output: 20,t,30,mt; which generates this weird ‘t’ instead of lb, and I have no idea why this is the case.
Similarly, when I type 30kg for weight, and 20cm for height. It generates this weird output:30,m,0, cm. The kg becomes a 'm' and the 20 is now a '0'!? Why is that the case? The expected output would be 30,kg,20,cm
I tried simply replacing the strings, but that doesn't solve the problem fundamentally. For instance, (considering when my user puts logical inputs like lb or kg for weight), I tried this substitution and it appears to work, but doesn't fix the issue of making 20 -> 0
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int main(){
int weight = 0;
int height= 0;
char wunit[] = "";
char hunit[] = "";
char wunit2[] = "lb";
char dummy[] = "t";
printf("Enter the body weight: ");
scanf("%d%s",&weight,wunit);
printf("Enter the height: ");
scanf("%d%s",&height,hunit);
if (strcmp(wunit,dummy)==0){
printf("%d,%s,%d,%s\n", weight, wunit2, height, hunit);
}
//printf("%d,%s,%d,%s", weight, wunit, height, hunit);
return 0;
}
I've also tried running it in codecollab, and it shows this error of "stack smashing detected" after I run it a few times, which got me more confused, what has it to do with this?
Thanks in advance.
wunit is an array of size 1 (it is initialized to "", which in chars looks like {'\0'}). What happens when you try to put lots of characters (say, "lb", which is {'l', 'b', '\0'}) into a memory location that is smaller than it should be?
scanf happily writes as many bytes as needed, smashing anything in its way ("stack-smashing", because wunit and all those local variables are stored on the stack). Try to give scanf more space, say using
char wunit[10] = "";
And never ever use "%s" directly. Limit the maximum of characters that you will allow scanf to place, for example using "%9s" to ensure that at most 9 characters + terminator (10 total) will be read.
This works for me:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int weight = 0;
int height = 0;
char wunit[10] = "";
char hunit[10] = "";
printf("Enter the body weight: ");
scanf("%d%9s",&weight,wunit);
printf("Enter the height: ");
scanf("%d%9s",&height,hunit);
printf("%d,%s,%d,%s", weight, wunit, height, hunit);
return 0;
}
Note: scanf with %s is rightfully considered very dangerous. See https://stackoverflow.com/a/2430310/15472

How to edit ELF files in Linux?

I have written two similar C programs. How can I make the outputs of both code same by editing one of the ELF files not the actual code?
/**
* prg1.c
*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 5;
int b = 10;
int sum;
sum = a + b;
printf("sum is %d\n", sum);
return(0);
}
/**
* prg2.c
*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 5;
int b = 20;
int sum;
sum = a + b;
printf("sum is %d\n", sum);
return(0);
}
In your second program's elf file find the occurrence of 20 and change it to 10.
To do that you can do something like this -
Find 14 (hex of 20) in your elf file and change it to A and making sure length is same by adding extra 0.
To do this you can use any elf editor, I use 'Hex Fiend' for mac.

How to get an array of strings without using argv - CS50 pset2

I'm currently doing the CS50 Harvard Course and I'm stuck in problem set 2.
I made this program that takes a name and prints the initials, it takes the name in the command line. How can I use get_string() instead of argv, and argc wich is very unorthodox and sloppy, so I can prompt the user to give me her/his name. Thank you.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
//How do I use Get_string() so I don't have to use argv and argc??
//iterate over strings on the vector (words)
for (int i = 0; i < argc; i++)
{
//prints the 0 character of each string, use "toupper" to convert into capital letters
printf("%c", toupper(argv[i][0]));
}
printf("\n");
}
use Array,
let's say for 10 names
string name[10];
for (int i = 0; i < 10; i++)
{
name[i] = get_string("Enter your name: /n");
}

In Ubuntu, Why the sequence is changed?

I compile this code in Ubuntu. I did it more than 10 times but I got only AAA BBB CCC . I believe sequence can be changed but I don't know why. Please somebody kindly tell me the reason.
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
void *thread_entry(void *ptr)
{
char *name = (char *)ptr;
printf("%s-A\n", name);
sleep(1); //sched_yield();
printf("%s-B\n", name);
sleep(1); //sched_yield();
printf("%s-C\n", name);
}
int main()
{
#define MAX_THREAD 3
pthread_t thread[MAX_THREAD];
char *thread_name[MAX_THREAD] = {"thread1", "thread2", "thread3"};
int i;
for (i = 0; i < MAX_THREAD; i++)
pthread_create(&thread[i], NULL, thread_entry, thread_name[i]);
for (i = 0; i < MAX_THREAD; i++)
pthread_join(thread[i], NULL);
return 0;
}
Theoretically it's possible, but it's very unlikely you would see another ordering.
You spawn 3 threads, then one of them prints "A" and waits for 1 second until it will print "B". One second of sleeping is far more than enough for the rest threads to print "A". Same for "B" and "C".

Why thread_id creates not in order?

I tried to create 10 threads, and output each tread index. My code is shown as below, I am wondering why they are repeating instead of arranging in order?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "util.h"
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
pthread_mutex_t request_buf_lock = PTHREAD_MUTEX_INITIALIZER;
void * worker(void *arg)
{
int thread_id = *(int*)arg;
// int requests_handled = 0;
//requests_handled = requests_handled + 1;
printf("%d\n",thread_id);
}
int main(int argc, char** argv)
{
pthread_t dispatchers[100];
pthread_t workers[100];
int i;
int * thread_id = malloc(sizeof(int));
for (i = 0; i < 10; i++) {
*thread_id = i;
pthread_create(&workers[i], NULL, worker, (void*)thread_id);
}
for (i = 0; i < 10; i++) {
pthread_join(workers[i], NULL);
}
return 0;
}
And the output result is:
4
5
5
6
6
6
7
8
9
9
But I expected it as:
0
1
2
3
4
5
6
7
8
9
Anyone has any idea or advice?
All 10 threads execute in parallel, and they all share a single int object, the one created by the call to malloc.
By the time your first thread executes its printf call, the value of *thread_id has been set to 4. Your second and third threads execute their printf calls when *thread_id has been set to 5. And so on.
If you allocate a separate int object for each thread (either by moving the malloc call inside the loop or just by declaring an array of ints), you'll get a unique thread id in each thread. But they're still likely to be printed in arbitrary order, since there's no synchronization among the threads.

Resources