Adding "th", "nd" or "rd" to a date in C - c

I'm modifying some driver software for my keyboard and part of it is a plugin that outputs the date to my keyboard screen. At the moment it says 1 January but I really want it to say 1st, 2nd, 3rd or 4th or whatever.
I've been looking everywhere for some kind of code that will give me some kind of an idea on how to do it but I can only find examples for C# and I'm using C.
Edit:
const char *ordinals[] = {"", "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", "20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "29th", "30th", "31st"};
sprintf(date, "%s %s", ordinals[t->tm_mday], mon);

Since you need this only for numbers 1 through 31, the easiest approach is to define an array of ordinals, like this:
const char *ordinals[] = {"", "1st", "2nd", "3rd", "4th"..., "31st"};
...
printf("%s of %s", ordinals[dayNumber], monthName);
This is better than doing it algorithmically, because it is more readable, and is easier to internationalize, should you run into this at some point later on.

This works for all nonnegative n:
char *suffix(int n)
{
switch (n % 100) {
case 11: case 12: case 13: return "th";
default: switch (n % 10) {
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default: return "th";
}
}
}
printf("%d%s\n", n, suffix(n));

void day_to_string(int day, char *buffer)
{
char *suff = "th";
switch(day)
{
case 1:
case 21:
case 31:
suff = "st";
break;
case 2:
case 22:
suff = "nd";
break;
case 3:
case 23:
suff = "rd";
break;
}
sprintf(buffer, "%d%s", day, suff);
}
Should do it. Note however that if you want to ever translate your program to another language, you may need to follow dasblinkenlight's suggestion, as you may find that the rules in some languages isn't the same as in English.

You can do it with a condition.
#include <stdio.h>
const char *suff;
switch (day)
{
case 1: /* fall-through */
case 21: /* fall-through */
case 31:
suff = "st";
break;
case 2: /* fall-through */
case 22:
suff = "nd";
break;
case 3: /* fall-through */
case 23:
suff = "rd";
break;
default:
suff = "th";
break;
}
printf("%d%s\n", day, suff);

Related

Changing number from character array to int array with decimal value

I am starting to learn C and I am having problem with changing numbers from character array to integer array. Here is my Code and I got random number and I have no idea why I am having those numbers.
The answer is 0 , 45, 45, 45
and I used 15 for plus sign, 25 for minus, 35 for multiply and 45 for division just for testing.
And also the answer which I want is if char[]="+123"-> int[0]=15;int[1]=1;int[2]=2;int[3]=3;
Thanks in advance and very much appreciated!
#include <stdio.h>
int main(){
int i=0;
char retezec[]="123+";
int array_length=(sizeof(retezec) / sizeof(retezec[0])-1);
int new_array[50];
while(retezec[i++]!='\0'){
switch(retezec[i]){
case '0':
new_array[i]=0;
case '1':
new_array[i]=1;
case '2':
new_array[i]=2;
case '3':
new_array[i]=3;
case '4':
new_array[i]=4;
case '5':
new_array[i]=5;
case '6':
new_array[i]=6;
case '7':
new_array[i]=7;
case '8':
new_array[i]=8;
case '9':
new_array[i]=9;
case '+':
new_array[i]=15;
case '-':
new_array[i]=25;
case '*':
new_array[i]=35;
case '/':
new_array[i]=45;
}
}
for(int i=0;i<array_length;i++){
printf("%d\n",new_array[i]);
}
}
Adding with the previous answers the reason you are getting 45 every time is that you haven't given the break keyword in every condition of switch case. Just add it and you will get the desired output :)
For example:
case '0':
new_array[i]=0;
break;
See the link below to have a good understanding. Hope it will help you.
https://www.programiz.com/c-programming/c-switch-case-statement
In your code -
while(retezec[i++]!='\0'){
switch(retezec[i]){
....
i is 0 when while loop condition is first evaluated, but in switch i already becomes 1. So your switch block checks elements from index 1 and not 0. Same way new_array is populated from index 1. The new_array[0] then have garbage value (as you are not initializing new_array)
You can use a for loop which will loop until array_length instead of the while loop like -
for (i = 0; i < array_length; i++) {
switch(retezec[i]) {
....
}
}
Also the switch case looks like an overkill. May be replace it with if-else
This can be boiled down significantly knowing that the C standard define the binary representation of 0 to 9 to necessarily be continuous.
#include <stdlib.h> /* for calloc() */
#include <stdio.h> /* for fprintf() */
int main(void)
{
char retezec[] = "123+";
size_t array_length = sizeof retezec / sizeof *retezec; /* sizeof evaluates to size_t not int. */
int * new_array = calloc(array_length * sizeof *new_array); /* Only get as much as needed, and have set to all 0s. */
if (NULL == new_array)
{
perror("calloc() failed");
return EXIT_FAILURE;
}
for (size_t i = 0; retezec[i] != '\0'; ++i) /* Use a for-loop where a for-loop can be used. */
{
switch(retezec[i])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
new_array[i] = retezec[i] - '0';
break;
case '+':
new_array[i] = 15;
break;
case '-':
new_array[i] = 25;
break;
case '*':
new_array[i] = 35;
break;
case '/':
new_array[i] = 45;
break;
default:
sprintf(stderr, "Unhandled character: '%c'\n", retezec[i]);
break;
}
}
for(size_t i = 0; i < array_length; ++i)
{
printf("%d\n", new_array[i]);
}
free(new_array);
return EXIT_SUCCESS;
}

How to get rid of the Heap-corruption error (Critical error c0000374) in C when converting hex into binary string?

Part of my project, where we have to take an input file with hex numbers and convert them to MIPS code, I want to convert the hex into binary so it'd be easier for me to convert it into MIPS. However, when I run the code, it crashes and quits when it reaches the part where it calls the converter function. GDB says its a critical error c0000374. How do I fix this?
I have tried giving the target string more space and it doesn't seem to have any effect. I have also tried using malloc to no avail.
char* convertBinary (int hex)
{
char* hexdec = calloc(9, sizeof(char));
char* bin = calloc(SIZE+1, sizeof(char));
snprintf(hexdec, SIZE, "%08X", hex);
long int i;
for (i = 0; hexdec[i]; ++i)
{
switch (hexdec[i])
{
case '0':
strcat(bin, "0000");
break;
case '1':
strcat(bin, "0001");
break;
case '2':
strcat(bin, "0010");
break;
case '3':
strcat(bin, "0011");
break;
case '4':
strcat(bin, "0100");
break;
case '5':
strcat(bin, "0101");
break;
case '6':
strcat(bin, "0110");
break;
case '7':
strcat(bin, "0111");
break;
case '8':
strcat(bin, "1000");
break;
case '9':
strcat(bin, "1001");
break;
case 'A':
case 'a':
strcat(bin, "1010");
break;
case 'B':
case 'b':
strcat(bin, "1011");
break;
case 'C':
case 'c':
strcat(bin, "1100");
break;
case 'D':
case 'd':
strcat(bin, "1101");
break;
case 'E':
case 'e':
strcat(bin, "1110");
break;
case 'F':
case 'f':
strcat(bin, "1111");
break;
default:
printf("\nInvalid hexadecimal digit %c",
hexdec[i]);
}
}
return bin;
}
Also, in case it helps, here is the main function where I call this function
int main ()
{
int command = 10010100; //This is in hex
char* binaryString = convertBinary(command);
printf("The coverted binary is: %s\n", binaryString);
}
I expect the function to return a string of the binary numbers that have been converted from an 8 digit hex number. However, the program just quits and doesn't output anything. When debugged with GDB, it lays out a warning saying,
warning: Critical error detected c0000374
There are multiple problems in your code:
You do not check the for memory allocation failure.
Since you allocate 9 bytes for hexdec, snprintf(hexdec, SIZE, "%08X", hex); should be
snprintf(hexdec, 9, "%08X", hex);
The definition of SIZE is missing, as well as the #include lines. Post the complete source of the program exhibiting the offending behavior.
There is no need to loop until the end of the string hexdec: since you convert the hex value with %08X, just loop with:
for (i = 0; i < 8; ++i)
You should free(hexdec) before leaving the convertBinary function.
The code and comment do not agree in int command = 10010100; //This is in hex, which one is wrong? Probably both.
There is no need to use long type for i, int will suffice. Conversely, the argument hex should have unsigned int type.
Here is a simplified version of your code:
#include <stdio.h>
#include <stdlib.h>
char *convertBinary(unsigned int hex) {
char *bin = calloc(33, 1);
int i;
if (bin) {
for (i = 32; i-- > 0;) {
bin[i] = '0' + (hex & 1);
hex >>= 1;
}
}
return bin;
}
int main() {
int command = 0x10010100; //This is in hex
char *binaryString = convertBinary(command);
if (binaryString == NULL) {
printf("Memory allocation failure\n");
} else {
printf("The converted binary is: %s\n", binaryString);
free(binaryString);
}
return 0;
}

Switch Statement with Array condition

I am having an impossible time trying to make this work. It is just a sample run of the code without the full options.
What is needed from the program is for the user to enter there choice, 1-3 or a-c. I am using a string in case the user enters more than just a single character. The switch case then should compare just the first char in the array to the cases. And the do while loop is to make sure it keeps going until they enter the right characters.
#include <stdio.h>
#define SIZE 81
void main(){
char thing[SIZE] = {3};
int rvalue;
do
{
scanf_s("%s", thing);
switch (thing[0])
{
case 'a':
case 1:
printf("first\n");
rvalue = 1;
break;
case 'b':
case 2:
printf("second\n");
rvalue = 2;
break;
case 'c':
case 3:
printf("third\n");
rvalue = 3;
break;
default:
printf("Wrong\n");
rvalue = 4;
break;
}
} while (rvalue == 4);
}
Change
scanf_s("%s", thing);
To
scanf_s("%s", thing,(unsigned int)sizeof(thing)); //Read the comments to know why the cast is required
This done because scanf and scanf_s are different function. scanf_s has an additional argument present to prevent buffer overflows.
Also change these
case 1:
case 2:
case 3:
To
case '1':
case '2':
case '3':
Because the character 1('1') and the rest of them are different from the integer 1. The characters(those enclosed in single quotes) have their values represented in the ASCII table.
As far as it seems, you want to print first when the first character in the thing string is a or 1, and so on.
The problem is that case 1: is not same as case '1':. 1 is an int, '1' is a char, and as you are comparing the first character of the string, you need to change your casestatements a bit.
Code:
#include <stdio.h>
#define SIZE 81
void main(){
char thing[SIZE] = {3};
int rvalue;
do
{
scanf_s("%s", thing,SIZE);
switch (thing[0])
{
case 'a':
case '1':
printf("first\n");
rvalue = 1;
break;
case 'b':
case '2':
printf("second\n");
rvalue = 2;
break;
case 'c':
case '3':
printf("third\n");
rvalue = 3;
break;
default:
printf("Wrong\n");
rvalue = 4;
break;
}
} while (rvalue == 4);
}

Switch statement not doing what I expect

What is wrong with this code:
switch (n)
{
case 0: strcpy(resultString, "Zero");
case 1: strcpy(resultString, "One");
case 2: strcpy(resultString, "Two");
case 3: strcpy(resultString, "Three");
case 4: strcpy(resultString, "Four");
case 5: strcpy(resultString, "Five");
case 6: strcpy(resultString, "Six");
case 7: strcpy(resultString, "Seven");
case 8: strcpy(resultString, "Eight");
case 9: strcpy(resultString, "Nine");
}
printf("%s", resultString);
It always prints "Nine" no matter the value of n. What am I doing wrong??
You need a break statement at the end of each case. Otherwise control falls straight through to the next case.
Change your code to:
switch (n)
{
case 0: strcpy(resultString, "Zero");
break;
case 1: strcpy(resultString, "One");
break;
case 2: strcpy(resultString, "Two");
break;
case 3: strcpy(resultString, "Three");
break;
case 4: strcpy(resultString, "Four");
break;
case 5: strcpy(resultString, "Five");
break;
case 6: strcpy(resultString, "Six");
break;
case 7: strcpy(resultString, "Seven");
break;
case 8: strcpy(resultString, "Eight");
break;
case 9: strcpy(resultString, "Nine");
break;
}
printf("%s", resultString);
You can find the switch statement documented here or in any book on the C language.
You need to break after each case.
case 0:
do soemthing;
break;
case 1:
do something;
break;
In many managed languages, it won't let "one case fall through to another," and throws an error. But C loves to let you do whatever you want!
You missed break; after each case
Example :
case 0: strcpy(resultString, "Zero");break;
..
..
case 8: .... ; break;
..
From the standard :
6.4.2 The switch statement [stmt.switch]
case and default labels in themselves do not alter the flow of control, which continues unimpeded across such labels. To exit from a switch, see break (6.6.1).
6.6.1 The break statement [stmt.break]
The break statement shall occur only in an iteration-statement or a switch statement and causes termination of the smallest enclosing iteration-statement or switch statement; control passes to the statement following the terminated statement, if any.
That means that is you don't use break after each case, you program will enter in the first case who matches the condition and will continue executing every line of the switch until the end.
You should just do something like :
switch( n )
{
case 0:
// ...
break; // <- Note the break
//...
default:
// ...
}

Making a switch statement in C with an array?

I am trying to make a switch statement that takes in a word into an array and then throws each letter through a switch statement and allocates a point to each letter depending on which letter it is and giving a final point value for the word, and I can't seem to get the array part right. Any help would be appreciated!
int main(){
int letter_points = 0;
char word[7];
int word_length = 7;
int i;
printf("Enter a Word\n");
scanf("%s", word);
for(i = 0; i < word_length; i++){
switch(word){
//1 point
case 'A':
case 'E':
case 'I':
case 'L':
case 'N':
case 'O':
case 'R':
case 'S':
case 'T':
case 'U':
letter_points++;
break;
//2 points
case 'D':
case 'G':
letter_points += 2;
break;
//3 points
case 'B':
case 'C':
case 'M':
case 'P':
letter_points += 3;
break;
//4 points
case 'F':
case 'H':
case 'V':
case 'W':
case 'Y':
letter_points += 4;
break;
//5 points
case 'K':
letter_points += 5;
break;
//8 points
case 'J':
case 'X':
letter_points += 8;
break;
//10 points
case 'Q':
case 'Z':
letter_points += 10;
break;
}
}
printf("%d\n", letter_points);
return;
}
It would probably be faster to have a lookup array:
int const letter_score[26] = { 1, 2, 1, 3, ..., 10 };
/* key: A B C D Z */
score += letter_score[c - 'A']; // or "toupper(word[i]) - 'A'"
Caveat: this requires an encoding in which the upper-case letters are arranged contiguously, such as Unicode or ASCII.
Try using this
switch(word[i]){
in the switch statement. As it stands, you are not testing each element in your array even though you are iterating over the range of the array. Having said that I would go for the approach suggested by Kerrek SB in the other answer. This is much neater and more compact.
The variable word is an array, but you want to switch on each character. Thus, you need:
switch(word[i])
In C, you cannot use arrays in switch (and expressions for case). Also, the type passed to switch() and types specified in each case must match. So the most you can do is switch on a character. You almost got it right though, except that you are passing the whole array into switch. Use index to reference a character instead. For example:
switch (word[i]) {
...
}
You have word as an array of size7, you cannot switch on the array, you have to swicth on each character of the array so use:
switch(word[i])

Resources