0

I cannot figure out how to assign an integer value to an array of string in C, assuming this is possible of course! I would like to change some elements from a char ** into different values and then re-assign them to their initial position into the array. Practically, I have two element, "Mon" and "Aug", which I would like to become "01" and "08"... So I tried something but unsuccessfully:

char *time_array[7] = {"45", "55", "11", "Mon", "29", "Aug", "2022"};
uint32_t day2convert = 1;
uint32_t month2convert = 8;
*time_array[3] = &day2convert;    // not even with a cast (char) which gave same results 
*time_array[5] = &month2convert;
for (j = 0; j < 7; ++j) 
printf("after conversion : %s\n", time_array[j]);
/* 

Results for the two elements are different at each main call, as I'm randomly picking values present in different memory allocations (maybe). Es. don, hug; 4on 8ug, ton xug... Moreover i tried also with strcpy function as:

strcpy(time_array[3], &day2convert);   //also with a cast (char)(&day2convert)

but still I retrieve a void string.

So, gently, I'm asking if there could be a way to do what I want in principle, but also asking for some explanations about array of string. Because what I learnt is that a char ** is an array of pointer so it should be right to assign a value to it as *array[ii] = &var (??? in search of confirmation)

Gipsy
  • 61
  • 4
  • 3
    `day2convert` isn't a character, and `&day2convert` isn't a string. If you want to convert an integer to a string you first of all need an array of characters big enough to fit all the digits of the number (including the string terminator character), then you e.g. `snprintf` to create a string from the number, and then make your array element point to that string. – Some programmer dude Aug 29 '22 at 10:03

2 Answers2

1

You will want to convert each of the 7 day names to a number.

I wrote this "hash function" for quickly getting back 1 to 7 for "Sun" to "Saturday" (it only needs the first two characters of the name, and is case insensitive).

It will return false positives, but allows you to test the string you have against only one possible day name. If the function returns 2, then the string can be checked as a variation of "Tu", "TUE" "Tuesday". You don't have to examine the other six day names as possibilities.

Return of 0 indicates it is not a weekday name.

// Convert a day name (or 3 letter abbrev.) to index (1-7, Sun=1). Beware false positives!
int wkdayOrd( char cp[] ) { return "65013427"[*cp/2 + ~cp[1] & 0x7] & 0x7; }

If you carefully replace 2 with 1, 3 with 2, 4 with 3, etc. in the quoted string, it will return Mon=1 and Sun=7 as you desire...

And for month names "Jan-December" (3 letters necessary) into 1 to 12. Again, this is a "hash function" and other words can/will result in "false positives" that must be confirmed against only one proper month name string.

int monthOrd( char cp[] ) { return "DIE@CB@LJF@HAG@K"[ cp[1]/4&7 ^ cp[2]*2 &0xF ] &0xF; }

Give it a play and let us know if it helps you get where you want to be.

EDIT:

Demonstrating functionality, here is an example that satisfies the OP question. The LUT values have been adjusted so that "Mon(day)" is day 1.

This does the conversion (trusting the source string) without invoking sprintf(). Here, printf() is used for 'diagnostic testing' only.

static int monthOrd( char cp[] ) { return "DIE@CB@LJF@HAG@K"[ cp[1]/4&7 ^ cp[2]*2 &0xF ] &0xF; }
static int wkdayOrd( char cp[] ) { return "54072316"[*cp/2 + ~cp[1] & 0x7] & 0x7; }

static char *toDigitStr( int val ) { // multiple execution overwrites result
    static char buf[3];
    buf[0] = (char)('0' + val/10);
    buf[1] = (char)('0' + val%10);
    buf[2] = '\0';
    return buf;
}

int main() {
    char *dayName = "Mon";
    printf( "%s ==> %s\n", dayName, toDigitStr( wkdayOrd( dayName ) ) );

    char *mthName = "Aug";
    printf( "%s ==> %s\n", mthName, toDigitStr( monthOrd( mthName ) ) );

    mthName = "DECEMBER";
    printf( "%s ==> %s\n", mthName, toDigitStr( monthOrd( mthName ) ) );

    return 0;
}

Output:

Mon ==> 01
Aug ==> 08
DECEMBER ==> 12
Fe2O3
  • 6,077
  • 2
  • 4
  • 20
  • Fe2O3, Interesting. Could avoid the last mask with `"\6\5\0\1\3\4\2\7"[*cp/2 + ~cp[1] & 7];` - but perhaps that is less clear. – chux - Reinstate Monica Aug 29 '22 at 17:20
  • @chux-ReinstateMonica Thanks. Need 3 bits x 7 days and some kind of LUT. Considered shifting & masking an `int`. but thought that was too cryptic... Play... `:-)` – Fe2O3 Aug 29 '22 at 20:48
  • Thanks, but i had already written the convertion functions myself...for the sake of purpose (which was not "how to convert day/month string to integer"!!!) I just put the two variables day2convert and month2convert! But it was interesting to read your code! thanks – Gipsy Aug 30 '22 at 13:19
1

... how to assign an integer value to an array of string (?)

time_array[] is not an array of strings. It is an array of pointers to strings. This distinction is important as string lifetimes need careful consideration. Here, the strings pointed to by time_array[i] are not certainty modifiable.

char *time_array[7] = {"45", "55", "11", "Mon", "29", "Aug", "2022"};

We could change the pointer by re-assigning a compound literal. It is easy to form a an integer like string with single digit values like 1-7. Yet the lifetime of the compound literal only lasts to the end of the block of code.

int day_index = 1;
time_array[3] = (char[3]){ '0', '0' + day_index, '\0'}; // , '\0' optional as rest is zero filled
// good for a while

Or perhaps make time_array[] an array of strings and then re-assign the indexed string.

char time_array[7][5] = {"45", "55", "11", "Mon", "29", "Aug", "2022"};
int day_index = 1;
strcpy(time_array[3], (char[3]){ '0', '0' + day_index });
// or
snprintf(time_array[3], sizeof time_array[3], "%02d", day_index);


// good indefinitely
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256