Randomize what string to print in c - c

I got a quick question. Is it possible to 'randomize' the output I get? For example in the first run I get 'Magic number 1', and when I run it again, I could get 'Magic number 3'. I couldn't find any help elsewhere.
#include <stdio.h>
int main() {
char *a = "Magic number 1\n";
char *b = "Magic number 2\n";
char *c = "Magic number 3\n";
printf("%s", b);
return 0;
}
I tried to edit the code to
printf("%s", a||b);
But || is used only to logic, right?

|| produces an int either 1 or 0 based on the truth of the logical OR statement.
What is happening in the statement printf("%s", a||b); is that the value 1 (since the addresses of the string pointers being compared are non-zero, thus the OR is true and returns 1) is attempted to be accessed as the pointer to a null-terminated string. This is undefined behavior, and very likely going to crash (if you're lucky).
If you want to print a random string from a set of variables in your code, what you can do is:
#include <stdlib.h>
#include <time.h>
// (in main())
srand((unsigned)time(NULL));
int r = rand()%3;
if(r == 0)
puts(a);
else if(r == 1)
puts(b);
else
puts(c);

What about something like this?
Instead of creating seperate variables for each of them, you can use 2D arrays.
int main() {
char arr[3][100] = {"Magic number 1\n", "Magic number 2\n", "Magic number 3\n"};
int i, range=3;
srand((unsigned)time(NULL));
i = rand()%range;
puts(arr[i]);
return 0;
}

Related

Decimal to binary using string in c....stuck with some conceptual error

#include<stdio.h>
char bin(int);
int main()
{
setbuf(stdout,NULL);
int num;
char res[50];
printf("Enter the number: ");
scanf ("%d",&num);
res=bin(num);
printf("%s",res);
return 0;
}
char bin(int num)
{
char str[50];
int i,val;
for(i=0;num>=0;i++)
{
val=num%2;
str[i]=val;
num=num/2;
}
return str;
}
I really cant understand the error in the usage of strings... to convert the decimal to binary. Whats the conceptual error Im not following?
char is a single character, so char bin(int) will not be able to return a string (i.e. a null-terminated array of characters). And you cannot "return" an an array of characters, because C does not allow to return any array as function result. You can just pass/return pointers to the begin of such arrays.
So I'd suggest to change the interface of bin to reicieve the result buffer as parameter. Don't forget to "close" the string, i.e. to write the string termination character after the last "actual" character:
void bin(int num, char* resultBuffer) {
...
resultBuffer[i] = '\0';
}
In main, you call it then like
bin(num, res);
Returning str amounts to returning a local variable, you can't do it, what you can do is to return a pointer to a previously allocated memory block that works as an array (as an alternative to the oher answer, which is a good solution).
To do this you can declare str as a pointer, allocate memory for it and return it, making sure the variable to which the value is assigned is also a pointer, all the rest can remain the same.
There are, however, problems with the bin function.
Consider the statement:
str[i] = val;
This will not work as expected you are assigning the int result of the operation, which will be 1 or 0, you need to convert this value to the respective character.
The loop for (i = 0; num >= 0; i++) is an infinite loop because num will never be negative, unless you provide it a negative number in which case it will break in the first iteration, that is to say this code only works with positive integers. You need > instead of >=.
Finally you need to null terminate the string when the conversion is complete.
Corrected code (Online):
#include <stdio.h>
#include <stdlib.h>
char *bin(int); //return pointer
int main() {
setbuf(stdout, NULL);
int num;
char *res; //use pointer to receive string assignment
printf("Enter the number: ");
scanf("%d", &num);
res = bin(num);
printf("%s", res);
return 0;
}
char *bin(int num) {
char *str = malloc(50); // allocate memory
int i, val;
for (i = 0; num > 0; i++) { // replacing >= with >
val = num % 2;
str[i] = val + '0'; // convert to character
num = num / 2;
}
str[i] = '\0'; //null terminate the string
return str;
}
Note that you should also check for the inputed value, if it is larger than what an int variable can hold it will result in undefined behavior.

program outputs exit phrase instead of words stored in C

So I was working on an assignment for school, and had written up a variation of this code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX 100
// This program takes an input of strings and prints them out with a new line separating each one.
int main() {
char *WordArray[MAX]; //initializing variables
int i = 0;
int count = 0;
printf("enter up to 100 words, that are 20 characters maximum \n");
for (i = 0; i <100; i++){ //runs while there's less than 100 inputs
char Array[1];
scanf("%s",Array); //stores string in the array
if (strcmp(Array, "STOP") == 0) { //compares the string with stop, and if it is, it breaks out of the loop
break;
}
WordArray[i]=Array; //stores the string in the pointer array
}
printf("The output is\n");
for (count = 0; count<i; count++){ //counts up to the amount of words stored
printf("%s\n",WordArray[count]); //outputs each pointer string
}
}
and I noticed that the output was printing "STOP" instead of the values stored. Anyone have any answers to why and/or how to fix it? I know one of the methods is to switch to a 2D array instead of using pointers, but I'm still baffled as to why a program like this wouldn't work.
Your char Array[1]; isn't large enough to store any but an empty string. Also, when it works, every pointer will point to the same string, which will be the last entry you made. This makes some corrections where commented.
#include <stdio.h>
#include <stdlib.h> // instead of ctype.h
#include <string.h>
#define MAX 100
// This program takes an input of strings and prints them out with a new line separating each one.
int main() {
char *WordArray[MAX];
int i = 0;
int count = 0;
printf("enter up to 100 words, that are 20 characters maximum \n");
for (i = 0; i <100; i++){
char Array[21]; // increase size of array
scanf("%20s",Array); // limit entry length
if (strcmp(Array, "STOP") == 0) {
break;
}
WordArray[i] = strdup(Array); // allocate memory for and copy string
}
printf("The output is\n");
for (count = 0; count<i; count++){
printf("%s\n",WordArray[count]);
}
// free each string's memory
for (count = 0; count<i; count++){
free(WordArray[count]);
}
}
Program output:
enter up to 100 words, that are 20 characters maximum
one two three STOP
The output is
one
two
three
Edit: note that your code contains another undefined behaviour besides the too-short string char Array[1] which is that you dereference the pointer you stored in char *WordArray[MAX];. The scope of Array is inside the for loop, and theoretically ceases to exist after the loop completes, so the pointer you store is invalid. Here, the word entered is duplicated with strdup so that doesn't apply.

Adding values from a file to an array until a certain character

I am working on a program that uses file redirection to read in a file, read one character per line until I reach a '0', store the characters in an array , and sort that array (from largest to smallest). Anyway, I really only need help with reading the characters until the zero shows up. Below is the text file that I am reading in:
f
k
s
j
p
a
v
r
t
u
h
m
g
e
b
y
n
z
w
l
i
x
q
c
o
d
0
Below is the code I have so far:
int main(void)
{
int i=0;
char array[100];
while(fscanf(stdin, "%c", &array[i]) && array[i]!='0')
{
i++;
}
int N = (sizeof(array)/sizeof(array[0]));
for(i=0;i<N;i++)
{
printf("%c", array[i]);
}
return(0);
}
When I run this program, it prints out every line of the file, including the zero. It also prints out some really weird characters after the zero (using gcc compiler). What am I doing wrong?
You need to set N to the value of i, currently it will always be 100
You use i to keep track of how many items you've read, but then you overwrite the value of i in your loop and print out all 100 elements, whether you stored something there or not.
Use different variable for counting the element than you do for looping, and use the count as your loop limit.
int count=0;
char array[100];
while(fscanf(stdin, "%c", &array[count]) && array[count]!='0')
{
count++;
}
for(i=0;i<count;i++)
{
printf("%c", array[i]);
}
fscanf needs to skip the separator (enter or space), else it will be incorporated into your list. Adding a space fixes that.
#include <stdio.h>
#include <stdlib.h>
int sort (const void *a,const void *b)
{
return ((int)*((unsigned char *)a)) - ((int)*((unsigned char *)b));
}
int main (void)
{
unsigned char array[100],i=0;
while (fscanf(stdin," %c", &array[i]) && array[i] != '0')
i++;
qsort (array,i,1,sort);
while (i)
printf ("%c\n", array[--i]);
}
It may seem this program sorts the wrong way around but the printing loop also happens to print in reverse, so that solves it neatly. As the array is unsigned char, the sort routine casts this to int to prevent possible overflow.

Why does adding a char (from argv) cause a no-result in C

first post (as you would know) and the form tells me that my title is bad and will get downvoted but I can't do better :) I've worked on this a bunch already.
I'm trying to cipher text by adding a number given in the command line to a string.
Why does
include <stdio.h>
int main(int argc, char * argv[])
{
printf("%i", argc);
char k = argv[1][0];
printf("%c", k);
char * s = "a";
printf("%c", s[0] + 0);
}
correctly print "a" (besides for printing argc and k)
but when the last line is
printf("%c", s[0] + k);
it just prints argc and k and then nothing. I wanted it to print 20a (when running ./question 0).
( I tried
char k = 0;
char * s = "a";
printf("%c", s[0] + k);
and that does work :( )
It seems like the fact that k is coming from argv is the issue but I don't have any idea why (not that I really understand any of this)
Thanks!
argv and argc and "a" are all red herrings. They have nothing to do with the problem. The problem lies in not understanding the difference between two character values, '0' and 0 (the latter is aso known as '\0').
In order to understand the difference I suggest experimenting with this program:
#include <stdio.h>
int main(void) {
char a = 'a', b = '0';
printf ("as char: a=%c b=%c sum=%c\n", a, b, a+b);
printf ("as int: a=%d b=%d sum=%d\n", a, b, a+b);
}
Use different values for b, including 0, 1, '0' and '1' and see what happens.
The answer is very simple.
The ASCII code of 'a' is 97.
Assuming only the printable characters in the arguments, the lowest printable ASCII code from the argv is 32.
97+32 = integer overflow which is UB - on ideone.com system it is -127
you can try yourself
https://ideone.com/D8DLcy
#include <stdio.h>
int main(void) {
for(char x = 32; x < 127; x++)
{
char m = 'a' + x;
printf("'a' + %c = char value in decimal is:%hhd - and the char is%c\n", x, m, m);
}
return 0;
}
The problem is that the expression s[0] + k is that adding a letter and a number together (conceptually speaking, ignoring the data types for a minute) can easily result in a value that is past the end of the alphabet, and printing it out as if it was a letter isn't necessarily going to work.
Bonus problem: reading the command line parameter into a single character isn't giving you a value of 0, but '0' which has a numerical value of 48. You can't just pull out the first character from the string. What if the user runs the program and passes 10 as a parameter?
You need to make sure that the result of your calculation is within the bounds of the alphabet.
As suggested by commenters above, take a look at the ASCII table, and try using some character constants sich as 'a' 'z' 'A' and 'Z' to modify the result
From the information you provided, it looks like you're implementing a simple shift cipher. Note the use of modulo for cases where the input for k is greater than 25.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING 16
int main(int argc, char *argv[])
{
char num[MAX_STRING];
char * s = "a";
int k;
if (argc == 2)
{
snprintf(num,MAX_STRING, argv[1], 10);
k = (int)strtol(num, NULL, 10) % 26;
printf("%c\n", s[0] + k);
}
else
{
fprintf(stderr,"Invalid number of arguments\n");
return(EXIT_FAILURE);
}
return(EXIT_SUCCESS);
}

scanf confusion with type error

I just make a program to guess some random pairs in an array,if guess right, delete this pair.
I met a problem that I can only type integer number.Everytime I tried to type like * ,the program will crash. I use a condition like:
if (scanf("%d",&temp)==1)
to try to fix my problem, but it really does'nt work.
here is my code and please give me some help:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int r[4]; //random
int s[8]; //store
char c[8]; //cover
int g[8]; //guess
int i;
int round=0;
int left = 4;
int point = 0;
int clear_index[2];
int temp;
// generate random number
for (i=0;i<4;i++)
{
r[i] = (rand()%10)+1;
s[i] = r[i];
s[i+4] = r[i];
}
// show the default number
printf("[show] ");
for (i=0;i<8;i++)
{
printf("%d ",s[i]);
c[i] = '*';
}
printf("\n");
while(left>0)
{
// print left
printf("[cover] ");
for (i=0;i<8;i++)
printf("%c ",c[i]);
printf("\n");
//guess
printf("[guess] ");
for(i=0;i<8;i++)
{
if (scanf("%d",&temp)==1)
g[i] = temp;
if (g[i] == s[i])
{
printf("v\n");
clear_index[point] = i;
point++;
}
}
if (point == 2)
{
for (i=0;i<2;i++)
c[clear_index[i]]=' ';
left-=1;
point = 0;
}
round+=1;
//left-=1;
}
printf("you won in %d round",round);
}
You get the segmentation fault, because, in case, you did not enter an integer, scanf will not return 1, and then, using g[i] will invoke undefined behavior.
FWIW, g is a local automatic array variable, and unless initialized explicitly, will have indeterminate value. Attempt to read the value will invoke the UB.
Solution:
Always initialize the local variables.
In case scanf() fails, you need to eat up the invalid input using some loop like while (getchar != '\n'); before you proceed to take the next input.
You are reading a number but the user can place a digit. To prevent this you can use the function atoi() from the library stdlib.h. It converts a string to a integer, if the integer is just number digits, it'll convert it to a integer. If it is a character it will return 0. So you just need to prevent the occurrence of a 0 after the atoi() function is called.

Resources