I'm doing the CS50x class and I am stuck at a glitch. I asked them what was going on and no one knew what was going on.
Whenever I try to print a lowercase f it always comes up as ?. Try doing 23 as the argument and abcdefghijklmnopqrstuvwxyz as the input. It's messed up. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main (int argc, string argv[]){
if(argc !=2){
return 1;
}
string x = GetString();
int key = atoi(argv[1]);
for(int a = 0, n = strlen(x); a < n; a++){
char i = key + x[a];
if(islower(x[a])){
if(i > 122){
i = (i-122) + 96;
}
}
if(isupper(x[a])){
if(i > 90){
i = (i-90) + 64;
}
}
printf("%c", i);
}
printf("\n");
return 0;
}
I suspect it's because your char i defaults to signed. When you add 23 to a lowercase letter, anything that is above 104 (being 127-23) is going to wrap around into negatives. Looking at your code, it will stay negative because it fails the subsequent tests and does not get modified.
It's usually best to do char arithmetic with int, then convert back to char... But you could probably fix this by using unsigned char.
Related
I want to modify a char by using a function and print it on the screen but my code cannot achieve this function. Here is my source code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
long M = 2147483647;
void IntroduceError(char k[],double p)
{
int i;
for ( i = 0; i < 8; i++) {
if ((double)random()/M <= p)
k[i] = 1;
}
}
int main(int argc, char *argv[])
{
char test[] = "11110000";
double rate = atof(argv[1]);
IntroduceError(test, rate);
printf("\nErrored codeword is : %s\n",test);
return 0;
}
k is a string i.e. array of characters, but you're assigning an integer value to it.
Instead of:
k[i] = 1;
You probably want:
k[i] = '1';
Also, you should call srandom at the start of your program to seed the random number generator, passing in at least the PID, i.e. srandom(getpid()); so that you don't get the same results every time.
get in the printf statement is not defined. If you change get with test it should compile.
Okay i have written up a code that converts a string to a decimal
however i am not understanding why it is core dumping on the second assert when the first one works fine
if i print out the return from the function it is actually returning what it is supposed to be returning but for some reason the assert fails
so can somebody help me understand what is going on with assert here? i dont understand why it is failing?
here is the code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
double myAtoD(char *);
int main(int argc, char *argv[]){
char *k="0.1";
char *l="0.141";
double m,n;
m = myAtoD(k);
n = myAtoD(l);
printf("%f\n",m);
assert(m==0.1);
printf("%f\n",n);
assert(n==0.141);
return 0;
}
double myAtoD (char *message){
int i=0;
int prior=0;
double num=0;
while(message[i]!='.'){
prior++;
i++;
}
i=0;
prior--;
while(message[i]!='\0'){
if(message[i]=='.')
i++;
printf("num is %f\nnew number to be added is %f\n\n",num, (message[i] - '0')*pow(10,prior));
num += (message[i] - '0')*pow(10,prior);
i++;
prior--;
}
return num;
}
You dealing with double precision issues.
The number 0.141 cannot be represented exactly by the computer, so you will have to instead check whether it is a small epsilon away from 0.141 instead.
Here is a better assertion.
assert(abs(n-0.141) < DBL_EPSILON);
For that constant, you will need to put #include <float.h> at the top of your source file.
A candidate improvement to myAtoD() that is more computationally stable. Although it provides a nice answer for "0.141", it may nor be the best for all input - need to do more testing. But #merlin2011 suggestion to allow a little wiggle room is good.
#include <ctype.h>
#include <math.h>
double myAtoD (const char *message){
double num = 0.0;
int dp = '.';
size_t dpi;
size_t i = 0;
for (i=0; message[i]; i++) {
int ch = (unsigned char) message[i];
if (ch == dp) {
dp = '\0';
dpi = i;
continue;
}
if (isdigit(ch)) {
num = num*10 + (ch - '0');
}
else {
break; // illegal character
}
}
if (dp == '\0') {
num /= pow10(i - dpi - 1);
}
return num;
}
[Edit]
A very precise and robust conversion of text to a double is non-trivial - best to do with some sort of extended precision. The above simple routine is certain to provide an answer within 2 ULP.
This is my code:
#include<stdio.h>
#include<stdlib.h>
main(){
char *alf="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!##$%&.",text[64];
int i, alfl=69;
srand(time(0));
for(i=0;i<64;i++)
text[i] = *(alf+rand()%alfl);
printf("%s",text);
}
But at the printf function it print an heart at final of the string.
As others have suggested in the comments (#mbratch and #KerrekSB) you need a null terminator at the end of your string.
Modify your code as follows:
#include<stdio.h>
#include<stdlib.h>
main(){
char *alf="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!##$%&.",text[64];
int i, alfl=69;
srand(time(0));
for(i=0;i<63;i++)
text[i] = *(alf+rand()%alfl);
text[i] = '\0';
printf("%s",text);
}
And it should work, but as #Simon suggested there can be other things that could help improve your code and understanding of C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 64
int main() { // If you don't add a return type, int is assumed. Please specify it as void or int.
const char *alf="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!##$%&."; // This string cant be assigned to. Make sure that you stay "const-correct".
char text[LEN]; // Please avoid magic numbers here too by using a constant
int i, alfl = strlen(alf); // As #Simon says, it is better to not use magic constants.
srand(time(0));
for(i=0;i<LEN-1;i++)
text[i] = *(alf+rand()%alfl);
text[i] = '\0'; // make sure to null terminate your string.
printf("%s",text);
return 0; // If your return type is int, you must return from the function.
}
Several suggestions:
main should return an int:
int main(void)
{
return 0;
}
You should use strlen to determine the length of strings:
alfl = strlen(alf);
It's easier to use array notation:
for(i = 0; i < 64; i++)
text[i] = alf[rand() % alfl];
If you use text like a string, it must be '\0' terminated:
text[63] = '\0';
I'm trying to create a char array made of some letters and numbers (the function was way more complex initially but i kept simplifying it to figure out why it doesn't work properly). So i have a char array in which i put 2 chars, and try to add some numbers to it.
For a reason i can't figure out, the numbers do not get added to the array. It might be really stupid but I'm new to C so here's the simplified code. Any help is much appreciated, thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char some_string[20];
char *make_str() {
some_string[0] = 'a';
some_string[1] = 'x';
int random = 0;
int rand_copy = 0;
random = (rand());
rand_copy = random;
int count = 2;
while ( rand_copy > 0 ) {
rand_copy = rand_copy / 10;
++count;
}
int i=2;
for (i=2; i<count; i++) {
some_string[i] = random%10;
random = random/10;
}
return (some_string);
}
int main(int argc, const char *argv[]) {
printf("the string is: %s\n",make_str());
return 0;
}
You have many problems:
resulting string is not zero-terminated. Add some_string[i] = '\0'; to fix this
character (char) is something like "a letter", but random % 10 produces a number (int) which when converted to character results in control code (ASCII characters 0-9 are control codes). You'd better use some_string[i] = (random % 10) + '0';
you're using fixed length string (20 characters), which may be enough, but it could lead to many problems. If you are a beginner and haven't learn dynamic memory allocation, than that's ok for now. But remember that fixed-length buffers are one of top-10 reasons for buggy C-code. And if you have to use fixed-length buffers (there are legitimate reason for doing this), ALLWAYS check if you are not overrunning the buffer. Use predefined constants for buffer length.
unless the whole point of your excercise is to try converting numbers to strings, use libc function like snprintf for printing anything into a string.
don't use global variable (some_string) and if you do (it's ok for a small example), there is no point in returning this value.
Slightly better version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_LENGTH 20
char some_string[BUF_LENGTH];
char *make_str() {
some_string[0] = 'a';
some_string[1] = 'x';
int random = rand();
int rand_copy = random;
int count = 2;
while (rand_copy > 0) {
rand_copy = rand_copy / 10;
++count;
}
int i;
for (i = 2; i < count; i++) {
/* check for buffer overflow. -1 is for terminating zero */
if (i >= BUF_LENGTH - 1) {
printf("error\n");
exit(EXIT_FAILURE);
}
some_string[i] = (random % 10) + '0';
random = random / 10;
}
/* zero-terminate the string */
some_string[i] = '\0';
return some_string;
}
int main(int argc, const char *argv[]) {
printf("the string is: %s\n",make_str());
return 0;
}
All I simply want to do is a make a record that starts with C or D randomly and has a number along with it 1-10. so a record would be C10. Can anyone tell me what I am doing wrong here?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
/*
*
*/
int main(int argc, char** argv)
{
char letter[] = { 'C', 'D' };
char record[2];
int r=1;
while (r < 11)
{
char num;
num = r;
record = (letter[rand()%2],num);
r++;
}
return 0;
}
For one obvious point, "C10" requires 4 characters, assuming you want it as a normal C string (3 in the string + 1 NUL terminator) but you've only made room for 2.
At least assuming you want your 1-10 as text characters, you'd typically want to do something like:
sprintf(record, "%c%d", letter[rand()%2], num);
Not that it matters a lot, but you seem to be including a lot of unnecessary headers for what you're doing.
record = (letter[rand()%2],num);
This is not a legal opporation... try this:
record[0] = letter[rand()%2];
record[1] = num;
You want the characters '0'-'9' popping up, but you are assigning the character r a numerical value between 0 and 10. Check out the table of ASCII characters.
I'd try it like this:
char record[4];
for (unsigned r = 0; r <= 10; ++r) {
snprintf(record, sizeof(record), "%c%d", letter[rand() % 2], r);
}