C- Find array length from pointer - c

So I've got this here:
#include <stdio.h>
char halloString[] = "Ha::ll::o";
char perfumeString[] = "47::11";
char veryLongString[] = "47::11::GHesd::dghsr::bfdr:hfgd46dG";
char *extract (char *input) {somethinghappenshere}
where extract needs to get all characters after the last double ":" of given input:
"o" for halloString
"11" for perfumeString
"bfdr:hfgd46dG" for veryLongString
In short, my issue is finding the length of the string *input points to. As far as I understand it that won't be happening without making something really sketchy.
Am I correct in assuming the length cannot be acquired in a good way?
And if so would it be a horrible idea to do, for example:
char stringToProcessTemp1[50];
char stringToProcessTemp2[50];
char stringToProcess[50];
for (int i = 0; i < 50; i++) {
stringToProcessTemp1[i] = input + i;
}
for (int i = 0; i < 50; i++) {
stringToProcessTemp2[i] = input + i;
}
for (int i = 0; i < 50; i++) {
if (stringToProcessTemp1[i] == stringToProcessTemp2[i]) {
stringToProcessTemp[i] = stringToProcessTemp1[i];
}
}
Later checking where the first empty index is and saving everything before it as the used String as from my very limited experience in C when you go outside of an array you tend to get different outputs every time therefore making the chance both Temp strings match for an extra element directly after the last one of the original string what I'd consider low enough.
It's honestly the only idea I've got right now.

Finding the length of a string is no problem. strlen will do that for you. However, you don't even need that.
You can use the strstr function to find a substring within a string, in this case "::". When you find one, keep looking right after the last one you found until you don't find it anymore, then the last one you found is the one you want. Then you want the substring that starts right after it.
char *extract(char *input)
{
char *last = NULL, *start = input, *curr;
while ((curr == strstr(start, "::")) != NULL) {
last = curr; // keep track of the last "::" found
start = last + 1; // move the starting string to right after the last "::"
// move up 1 instead of 2 in case of ":::"
}
if (last != NULL) {
last +=2; // We found one; move just past the "::"
}
return last;
}

C strings, which are really only an array of characters, are by definition terminated by '\0'. So, for a well formed C string you can always get the length of the string by using strlen().
If, however, your string is not null-terminated, there is no way to determine it's length, and it is not a C string by definition any more, but just an array of characters.

Related

Modify an old string into an new string from a file

Say I have a birthday that is written as 04251993 in some file that
I want to format it as 04/25/1993
I'm assuming that I should make an empty string, or modify the old string into the new string.
I'm not quite sure of how to do that: need some help on writing the function.
I started it out like this.
the first two chars need to be the month with a slash after, 2 more chars with a slash after and then lasty 4 more chars to put out the year.
void timef(char str[]){
printf("%c, str[0]) ?
Make a character array large enough on the heap. Then go through the
characters and insert the slashes. Use fputs to place it in a file. Repeat.
Use "%.*s" to scan the original string and then write to a new one
const char *src = "04251993";
char dest[11];
if (strlen(src) >= 8) {
sprintf(dest, "%.2s/%.2s/%.4s", src, src + 2, src + 4);
}
You can either write a function that is general or one that only performs an operation within set bounds. For this answer, let's just work on the latter. This means, I'll assume your string is always a fixed size of 9 chars (including '\0') and the packing of the data is "mm/dd/yyyy".
From there, you just need to work out how much larger the new string needs to be, and that's originalString + 2 chars, so you need a new array of 11 characters.
char newDate[11] = "";
Then you need to loop through the contents of the original string array and place each character into the new array, as well as adding the slashes as you go. So something like this:
int main()
{
int newSize = 11;
char oldDate[9] = "04231993";
char newDate[11] = "";
for(int i = 0, j = 0; i < newSize && j < oldSize; i++, j++){
if(i == 2){
newDate[i] = '/';
i++;
}
if(i == 5){
newDate[i] = '/';
i++;
}
newDate[i] = oldDate[j];
}
printf("%s", newDate);
}
That's REALLY simple and only to illustrate the basic concept. I would recommend working on your own, more robust version.

How to rewrite an char array in c?

I've searched around for a quiet some time but surprisingly I couldn't find an answer to it:
I want to rewrite a char array starting from [0], but all what's happening is: it's always appending. Here's my code:
The algorithm is: I have a very long string which I like to break into several lines (wherever there is a blank space at the end of a line). Each line shall be saved in an array Index (lineContent);
void print_text(char* content, int menu_width, int which_selected, int menu_height, int scroll_pos)
{
int posCounter = 0;
int charCounter = menu_width-10;
int printOutCounter;
char* lineContent[400]; // 400 lines max
short spaceFound;
while (strlen(content) > menu_width) // If string is longer than 1 line
{
//Interesting Part ---------- START
char changeString [strlen(content)];
char printString [menu_width-10];
spaceFound = 0;
charCounter = menu_width-10;
lineContent[posCounter] = malloc(MAXITEMSTR);
while (spaceFound == 0)
{
if (content[charCounter] == ' ')
{
// I guess the error goes between here ...
strncpy(changeString,content,strlen(content));
strncpy(printString,content,menu_width-10);
// ...and here
memmove(&changeString[0], &changeString[charCounter], strlen(content));
content=changeString;
lineContent[posCounter]=printString;
strcat(lineContent[posCounter],"\0");
posCounter++;
spaceFound = 1;
//Interesting Part ---------- END
}
charCounter--;
if (charCounter <= 0)
spaceFound = 1;
}
}
}
As I said, in the end, when checking the content of lineContent, every entry is the same (the one from the last line).
I think this is because, strcpy just appends to the end, therefor I have to clear the array, to erase the former line. So it will start from [0] and not from the last printed letter.
Has anybody an idea how to do this? Is there a function that overwrites a char array instead of appending it?
Kind Regards
Strcat appends to the end, strcpy overwrites the value stored in the string.

reading strings to a char array and then getting the size of the strings

Im working on a project and I am stumped on this part.
I need to read words from stdin and place them in a char array and use an array of pointers to point to each word since they will be jagged. where numwords is an int read in representing the number of words.
char words[10000];
char *wordp[2000];
the problem is that I can only use the pointers to add the words.I can no longer use the [] to help.
*wordp = words; //set the first pointer to the beginning of the char array.
while (t < numwords){
scanf("%s", *(wordp + t)) //this is the part I dont know
wordp = words + charcounter; //charcounter is the num of chars in the prev word
t++;
}
for(int i = 0;words+i != '\n';i++){
charcounter++;
}
any help would be great I am so confused when it comes to pointers and arrays.
Your code will be much more manageable if you use an additional pointer
reference and increment that directly. In this way you won't have to do any
mental math. Additionally you need to be incrementing the reference before
reading in the next string, scanf doesn't move the pointer for you.
char buffer[10000];
char* words[200];
int number_of_words = 200;
int current_words_index = 0;
// This is what we are going to use to write to the buffer
char* current_buffer_prt = buffer;
// quick memset (as I don't remember if c does this for us)
for (int i = 0; i < 10000; i++)
buffer[i] = '\0';
while (current_words_index < number_of_words) {
// Store a pointer to the current word before doing anything to it
words[current_word_index] = current_buffer_ptr;
// Read the word into the buffer
scanf("%s", current_buffer_ptr);
// NOTE: The above line could also be written
// scanf("%s", words[current_word_index]);
// this is how we move the buffer to it's next empty position.
while (current_buffer_ptr != '\n')
current_buffer_ptr++;
// this ensures we don't overwrite the previous \n char
current_buffer_ptr++;
current_words_index += 1;
}
What you want to do is relatively straightforward. You've got an array of 10,000 chars for storage, and 2000 pointers. So to start with you'll want to assign the first pointer to the start of the array:
wordp[0] = &words[0];
In pointer form this is:
*(wordp + 0) = words + 0;
I've used the zeros to show how it relates to the arrays. In general, to set each pointer to each element:
*(wordp + i) == wordp[i]
words + i == &words[i]
So all you need to do is keep track of where you are in the pointer array, and as long as you've assigned correctly, the pointer array will keep track of the position in your char array.

Append to string in C

So I have a string which will have the following rough format: string # more than one string here.
What I want to do is strip everything after the #. How would I do that? Furthermore, what if I just want to keep the initial string, and take everything after the space and the #?
I have the following code, but obviously appending something to a NULL string does not work as expected:
char *inst_ptr holds the whole string.
char *lbl = NULL;
int len = 0;
size_t inst_len = strlen(inst_ptr);
for (int t = 0; t < inst_len; t++) {
if (inst_ptr[t] == '#')
break;
else {
printf("len %d\n", len);
lbl[len] = inst_ptr[t];
lbl[len+1] = '\0';
len = strlen(lbl);
}
}
EDIT:
Basically, assume I have the following string:
loop # hello world!
I just want to extract loop in another string. What I am doing above is having lbl as a NULL string, and run a loop across the original string. As long as the character is not #, i just "append" the character with a null terminator as shown above.
Perhaps you should check section 7.21 in the standard for some inspiration.
The best approach depends on the rest of your application.
If you don't care about the original data, you could just use
strtok(inst_ptr, "#");
Or it might be better to allocate-and-copy just the data you need:
char * temp = strchr(inst_ptr, '#');
char * lbl;
if (temp)
lbl = strndup(inst_ptr, temp - inst_ptr);
else
lbl = strdup(inst_ptr);
Please note that the above are the minimal implemenations I've come to think of off the top of my head, not necessarily the best ones.
First, you are doing
char *lbl = NULL;
Then you are doing
lbl[len]
You're trying to dereference a NULL pointer and causing undefined behaviour.
First, you need to allocate memory for that string (calloc allocates the memory and sets it all to 0, which will obviate the need to manually add the null terminator):
char *lbl = calloc(inst_len + 1, 1);
Then you need to fix your loop, some of the things are in the wrong place. It should be
for (int t = 0; t < inst_len; t++) {
if (inst_ptr[t] == '#') {
len = t - 1; // strlen(lbl) is redundant
break;
} else
lbl[t] = inst_ptr[t];
}
Then when you are done, free the memory you allocated so as not to cause a memory leak:
free(lbl);

Efficient search for shortest and longest strings from an array of long strings in C

Given an array of pointers to ordinary C NUL-terminated (and typically very long) strings, how can we best find the smallest and the largest strings?
using strlen on each entry of your array.
Maybe for looping through them will help? - Ok, you don't want C++ idea, let's see:
Ok, again:
char **strings; // initialized
int stringsNumber = 500; // number of string in first dimension
int longestLen = 0;
int shortestLen = MAX_INT; // or other REALLY BIG number ;]
char *longest = NULL;
char *shortest = NULL;
int current = 0;
for(int i =0; i < stringsNumber; i++)
{
current = strlen(strings[i]);
if(current > longestLen) { longestLen = current; longest = strings[i]; }
if(current < shortestLen) { shortestLen = current; shortest = strings[i]; }
}
You can have another array of char pointers of size n, with its ith pointer pointing to the start of the ith string.
Increment each pointer till it reaches the end.
The first one to reach the end was the pointer to the shortest string.
The last one to reach the end was the pointer to the longest string.
If the strings are really really long, you should consider saving them with a length attribute, which is computed already during entering the strings.
If it's given to you and you don't manage it - iteration over array and strlen.
If you manage it - consider using std::string or pair<char *, int>(string,length) to optimize your code as well as replacing array of pointers with some ordered container.

Resources