How to convert a string value to numerical value? - c

I have tried this code to separate my Str[] string into 2 string, but my problem is "I want to separate John(name) as string and 100(marks) as integer",How can I do it, any suggestion?
#include <stdio.h>
#include <string.h>
void main()
{
char Str[] = "John,100";
int i, j, xchange;
char name[50];
char marks[10];
j = 0; xchange = 0;
for(i=0; Str[i]!='\0'; i++){
if(Str[i]!=',' && xchange!=-1){
name[i] = Str[i];
}else{
xchange = -1;
}
if(xchange==-1){
marks[j++] = Str[i+1];
}
}
printf("Student name is %s\n", name);
printf("Student marks is %s", marks);
}

How to separate "John,100" into 2 strings?
There are three common approaches:
Use strtok() to split the string into individual tokens. This will modify the original string, but is quite simple to implement:
int main(void)
{
char line[] = "John,100;passed";
char *name, *score, *status;
/* Detach the initial part of the line,
up to the first comma, and set name
to point to that part. */
name = strtok(line, ",");
/* Detach the next part of the line,
up to the next comma or semicolon,
setting score to point to that part. */
score = strtok(NULL, ",;");
/* Detach the final part of the line,
setting status to point to it. */
status = strtok(NULL, "");
Note that if you change char line[] = "John,100"; then status will be NULL, but the code is otherwise safe to run.
So, in practice, if you required all three fields to exist in line, it would be sufficient to ensure the last one was not NULL:
if (!status) {
fprintf(stderr, "line[] did not have three fields!\n");
return EXIT_FAILURE;
}
Use sscanf() to convert the string. For example,
char line[] = "John,100";
char name[20];
int score;
if (sscanf(line, "%19[^,],%d", name, &score) != 2) {
fprintf(stderr, "Cannot parse line[] correctly.\n");
return EXIT_FAILURE;
}
Here, the 19 refers to the number of chars in name (one is always reserved for the end-of-string nul char, '\0'), and [^,] is a string conversion, consuming everything except a comma. %d converts an int. The return value is the number of successful conversions.
This approach does not modify the original string, and it allows you to try a number of different parsing patterns; as long as you try them the most complex one first, you can allow multiple input formats with very little added code. I do this regularly when taking 2D or 3D vectors as inputs.
The downside is that sscanf() (all functions in the scanf family) ignores overflow. For example, on 32-bit architectures, the largest int is 2147483647, but scanf functions will happily convert e.g. 9999999999 to 1410065407 (or some other value!) without returning an error. You can only assume the numerical inputs are sane and within the limits; you cannot verify.
Use helper functions to tokenise and/or parse the string.
Typically, the helper functions are something like
char *parse_string(char *source, char **to);
char *parse_long(char *source, long *to);
where source is a pointer to the next character in the string to be parsed, and to is a pointer to where the parsed value will be stored; or
char *next_string(char **source);
long next_long(char **source);
where source is a pointer to a pointer to the next character in the string to be parsed, and the return value is the value of the extracted token.
These tend to be longer than above, and if written by me, then quite paranoid about the inputs they accept. (I want my programs to complain if their input cannot be reliably parsed, rather than silently produce garbage.)
If the data is some variant of CSV (comma-separated values) read from a file, then the proper approach is a different one: instead of reading the file line by line, you read the file token by token.
The only "trick" is to remember the separator character that ended the token (you can use ungetc() for this), and use a different function to (read and ignore the rest of the tokens in the current record, and) consume the newline separator.

Related

Extracting numbers from the string using regex

I am trying to extract the number 4 and 3 from the string /ab/cd__my__sep__4__some__sep__3. I am trying with regex but not sure how would I do this. I wrote the following code, but it just prints out __my__sep__4__some__sep__3
#include <stdio.h>
#include <regex.h>
#include <string.h>
#include <stdlib.h>
int main() {
char* s = "/ab/cd__my__sep__4__some__sep__3";
regex_t regex;
int reti = regcomp(&regex,"__my__sep__([0-9]+)",REG_EXTENDED);
if(reti!=0) {
exit(-1);
}else {
regmatch_t match[2];
reti = regexec(&regex, s, 2, match, 0);
if(reti == 0) {
char *v = &s[match[1].rm_so];
ssize_t fl;
sscanf(v, "%zu", &fl);
printf("%s",v);
}else {
printf("else");
}
}
}
How could I extract the numbers 4 and 3 ?
match[0] refers to the part of the text matched by the entire pattern. match[1] is the match corresponding to the first capture (parenthesized subpattern).
Note that &s[match[1].rm_so] gives you a pointer to the start of the capture, but if you print the string at that point, you will get the part of the string starting at the beginning of the capture. In this case, that doesn't really matter. Since you're using sscanf to extract the integer value of the captured text, the fact that the substring isn't terminated immediately doesn't matter; it's not going to be followed by a digit, and sscanf will stop at the first non-digit.
But in the general case, it's possible that it will not be so easy to identify the end of the matched capture, and you can use one of these techniques:
If you want to print the capture, you can use a computed string width format: (See Note 1.)
printf("%.*s\n", match[1].rm_eo - match[1].rm_so, &s[match[1].rm_so]);
If you have strndup, you can easily create a dynamically-allocated copy of the capture: (See Note 2.)
char* capture = strndup(&s[match[1].rm_so], match[1].rm_eo - match[1].rm_so);
As a quick-and-dirty hack, it is also possible to just insert a NUL terminator (assuming that the searched string is not immutable, which means that it cannot be a string literal). You'll probably want to save the old value of the following character so that you can restore the string to it's original state:
char* capture = &s[match[1].rm_so];
char* rest = &s[match[1].rm_eo];
char saved_char = *rest;
*rest = 0;
/* capture now points to a NUL-terminated string. */
/* ... */
/* restore s */
*rest = saved_char;
None of the above is really necessary in the context of the original question, since the sscanf as written will work perfectly if you change the start of the string to scan from match[0] to match[1].
Notes:
In the general case, you should test to make sure that a capture was actually found before trying to use its offset. The rm_so member will be -1 if the capture was not found during the regex search That doesn't necessarily mean that the search failed, because the capture could be part of an alternative not used in the match.
Don't forget to free the copy when you no longer need it. If you don't have strndup, it's pretty easy to implement. But watch out for the corner cases.
Since you are using sscanf(), there is no need to use a regex. You can parse the two numbers from your string using sscanf() alone using the format string: "%*[^0-9]%d%*[^0-9]%d" where "%*[^0-9]" uses the assignment suppression '*' to read and discard all non-digit characters and then uses "%d" to extract the integer value. The full format-string just repeats those two patterns twice.
A short example using your input could be:
#include <stdio.h>
int main (void) {
char *s = "/ab/cd__my__sep__4__some__sep__3";
int a, b;
if (sscanf (s, "%*[^0-9]%d%*[^0-9]%d", &a, &b) == 2)
printf ("a: %d\nb: %d\n", a, b);
else {
fputs ("error: parse of integers failed.\n", stderr);
return 1;
}
}
Example Use/Output
$ ./bin/parse2ints
a: 4
b: 3
If you find yourself attempting to parse something that sscanf() cannot handle, then a regex is appropriate. Here, sscanf() is more than capable of handling your needs alone.
Create a regex format that only holds [0-9]. Then create a separate boolean function checking whether a character belongs or not to your regex. Then apply the function to your string. If true, add the character to the string you want to output

C - Print ASCII Value for Each Character in a String

I'm new to C and I'm trying to write a program that prints the ASCII value for every letter in a name that the user enters. I attempted to store the letters in an array and try to print each ASCII value and letter of the name separately but, for some reason, it only prints the value of the first letter.
For example, if I write "Anna" it just prints 65 and not the values for the other letters in the name. I think it has something to do with my sizeof(name)/sizeof(char) part of the for loop, because when I print it separately, it only prints out 1.
I can't figure out how to fix it:
#include <stdio.h>
int main(){
int e;
char name[] = "";
printf("Enter a name : \n");
scanf("%c",&name);
for(int i = 0; i < (sizeof(name)/sizeof(char)); i++){
e = name[i];
printf("The ASCII value of the letter %c is : %d \n",name[i],e);
}
int n = (sizeof(name)/sizeof(char));
printf("%d", n);
}
Here's a corrected, annotated version:
#include <stdio.h>
#include <string.h>
int main() {
int e;
char name[100] = ""; // Allow for up to 100 characters
printf("Enter a name : \n");
// scanf("%c", &name); // %c reads a single character
scanf("%99s", name); // Use %s to read a string! %99s to limit input size!
// for (int i = 0; i < (sizeof(name) / sizeof(char)); i++) { // sizeof(name) / sizeof(char) is a fixed value!
size_t len = strlen(name); // Use this library function to get string length
for (size_t i = 0; i < len; i++) { // Saves calculating each time!
e = name[i];
printf("The ASCII value of the letter %c is : %d \n", name[i], e);
}
printf("\n Name length = %zu\n", strlen(name)); // Given length!
int n = (sizeof(name) / sizeof(char)); // As noted above, this will be ...
printf("%d", n); // ... a fixed value (100, as it stands).
return 0; // ALWAYS return an integer from main!
}
But also read the comments given in your question!
This is a rather long answer, feel free to skip to the end for the code example.
First of all, by initialising a char array with unspecified length, you are making that array have length 1 (it only contains the empty string). The key issue here is that arrays in C are fixed size, so name will not grow larger.
Second, the format specifier %c causes scanf to only ever read one byte. This means that even if you had made a larger array, you would only be reading one byte to it anyway.
The parameter you're giving to scanf is erroneous, but accidentally works - you're passing a pointer to an array when it expects a pointer to char. It works because the pointer to the array points at the first element of the array. Luckily this is an easy fix, an array of a type can be passed to a function expecting a pointer to that type - it is said to "decay" to a pointer. So you could just pass name instead.
As a result of these two actions, you now have a situation where name is of length 1, and you have read exactly one byte into it. The next issue is sizeof(name)/sizeof(char) - this will always equal 1 in your program. sizeof char is defined to always equal 1, so using it as a divisor causes no effect, and we already know sizeof name is equal to 1. This means your for loop will only ever read one byte from the array. For the exact same reason n is equal to 1. This is not erroneous per se, it's just probably not what you expected.
The solution to this can be done in a couple of ways, but I'll show one. First of all, you don't want to initialize name as you do, because it always creates an array of size 1. Instead you want to manually specify a larger size for the array, for instance 100 bytes (of which the last one will be dedicated to the terminating null byte).
char name[100];
/* You might want to zero out the array too by eg. using memset. It's not
necessary in this case, but arrays are allowed to contain anything unless
and until you replace their contents.
Parameters are target, byte to fill it with, and amount of bytes to fill */
memset(name, 0, sizeof(name));
Second, you don't necessarily want to use scanf at all if you're reading just a byte string from standard input instead of a more complex formatted string. You could eg. use fgets to read an entire line from standard input, though that also includes the newline character, which we'll have to strip.
/* The parameters are target to write to, bytes to write, and file to read from.
fgets writes a null terminator automatically after the string, so we will
read at most sizeof(name) - 1 bytes.
*/
fgets(name, sizeof(name), stdin);
Now you've read the name to memory. But the size of name the array hasn't changed, so if you used the rest of the code as is you would get a lot of messages saying The ASCII value of the letter is : 0. To get the meaningful length of the string, we'll use strlen.
NOTE: strlen is generally unsafe to use on arbitrary strings that might not be properly null-terminated as it will keep reading until it finds a zero byte, but we only get a portable bounds-checked version strnlen_s in C11. In this case we also know that the string is null-terminated, because fgets deals with that.
/* size_t is a large, unsigned integer type big enough to contain the
theoretical maximum size of an object, so size functions often return
size_t.
strlen counts the amount of bytes before the first null (0) byte */
size_t n = strlen(name);
Now that we have the length of the string, we can check if the last byte is the newline character, and remove it if so.
/* Assuming every line ends with a newline, we can simply zero out the last
byte if it's '\n' */
if (name[n - 1] == '\n') {
name[n - 1] = '\0';
/* The string is now 1 byte shorter, because we removed the newline.
We don't need to calculate strlen again, we can just do it manually. */
--n;
}
The loop looks quite similar, as it was mostly fine to begin with. Mostly, we want to avoid issues that can arise from comparing a signed int and an unsigned size_t, so we'll also make i be type size_t.
for (size_t i = 0; i < n; i++) {
int e = name[i];
printf("The ASCII value of the letter %c is : %d \n", name[i], e);
}
Putting it all together, we get
#include <stdio.h>
#include <string.h>
int main() {
char name[100];
memset(name, 0, sizeof(name));
printf("Enter a name : \n");
fgets(name, sizeof(name), stdin);
size_t n = strlen(name);
if (n > 0 && name[n - 1] == '\n') {
name[n - 1] = '\0';
--n;
}
for (size_t i = 0; i < n; i++){
int e = name[i];
printf("The ASCII value of the letter %c is : %d \n", name[i], e);
}
/* To correctly print a size_t, use %zu */
printf("%zu\n", n);
/* In C99 main implicitly returns 0 if you don't add a return value
yourself, but it's a good habit to remember to return from functions. */
return 0;
}
Which should work pretty much as expected.
Additional notes:
This code should be valid C99, but I believe it's not valid C89. If you need to write to the older standard, there are several things you need to do differently. Fortunately, your compiler should warn you about those issues if you tell it which standard you want to use. C99 is probably the default these days, but older code still exists.
It's a bit inflexible to be reading strings into fixed-size buffers like this, so in a real situation you might want to have a way of dynamically increasing the size of the buffer as necessary. This will probably require you to use C's manual memory management functionality like malloc and realloc, which aren't particularly difficult but take greater care to avoid issues like memory leaks.
It's not guaranteed the strings you're reading are in any specific encoding, and C strings aren't really ideal for handling text that isn't encoded in a single-byte encoding. There is support for "wide character strings" but probably more often you'll be handling char strings containing UTF-8 where a single codepoint might be multiple bytes, and might not even represent an individual letter as such. In a more general-purpose program, you should keep this in mind.
If we need write a code to get ASCII values of all elements in a string, then we need to use "%d" instead of "%c". By doing this %d takes the corresponding ascii value of the following character.
If we need to only print the ascii value of each character in the string. Then this code will work:
#include <stdio.h>
char str[100];
int x;
int main(){
scanf("%s",str);
for(x=0;str[x]!='\0';x++){
printf("%d\n",str[x]);
}
}
To store all corresponding ASCII value of character in a new variable, we need to declare an integer variable and assign it to character. By this way the integer variable stores ascii value of character. The code is:
#include <stdio.h>
char str[100];
int x,ascii;
int main(){
scanf("%s",str);
for(x=0;str[x]!='\0';x++){
ascii=str[x];
printf("%d\n",ascii);
}
}
I hope this answer helped you.....😊

strtok() C-Strings to Array

Currently learning C, Having some trouble with passing c-string tokens into array. Lines come in by standard input, strtok is used to split the line up, and I want to put each into an array properly. an EOF check is required for exiting the input stream. Here's what I have, set up so that it will print the tokens back to me (these tokens will be converted to ASCII in a different code segment, just trying to get this part to work first).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char string[1024]; //Initialize a char array of 1024 (input limit)
char *token;
char *token_arr[1024]; //array to store tokens.
char *out; //used
int count = 0;
while(fgets(string, 1023, stdin) != NULL) //Read lines from standard input until EOF is detected.
{
if (count == 0)
token = strtok(string, " \n"); //If first loop, Get the first token of current input
while (token != NULL) //read tokens into the array and increment the counter until all tokens are stored
{
token_arr[count] = token;
count++;
token = strtok(NULL, " \n");
}
}
for (int i = 0; i < count; i++)
printf("%s\n", token_arr[i]);
return 0;
}
this seems like proper logic to me, but then i'm still learning. The issue seems to be with streaming in multiple lines before sending the EOF signal with ctrl-D.
For example, given an input of:
this line will be fine
the program returns:
this
line
will
be
fine
But if given:
none of this
is going to work
It returns:
is going to work
ing to work
to work
any help is greatly appreciated. I'll keep working at it in the meantime.
There are a couple of issues here:
You never call token = strtok(string, " \n"); again once the string is "reset" to a new value, so strtok() still thinks it is tokenizing your original string.
strtok is returning pointers to "substrings" inside string. You are changing the contents of what is in string and so your second line effectively corrupts your first (since the original contents of string are overwritten).
To do what you want you need to either read each line into a different buffer or duplicate the strings returned by strtok (strdup() is one way - just remember to free() each copy...)

lack of understanding about sscanf usage

I would like to parse a specific line. So, I wrote the following piece of code in order to test the logic but I probably understand something wrongly :
typedef struct vers
{
char tu8UVersion[5];
char tu8UCommit[32];
}tst_prg_versions;
int main(int argc, char **argv)
{
tst_prg_versions lstVer;
char buf1[32];
char buf2[32];
char str[] = "BOARD-VERS-v1.0.0-git+9abc12345a";
sscanf(str, "BOARD-VERS-v%5s-git+%s", lstVer.tu8UVersion, lstVer.tu8UCommit);
printf("vers='%s'\n", lstVer.tu8UVersion);
printf("commit='%s'\n", lstVer.tu8UCommit);
sscanf(str, "BOARD-VERS-v%5s-git+%s", buf1, buf2);
printf("vers='%s'\n", buf1);
printf("commit='%s'\n", buf2);
return 0;
}
Once executed it returns :
vers='1.0.09abc12345a'
commit='9abc12345a'
vers='1.0.0'
commit='9abc12345a
Why the first vers is equals to 1.0.09abc12345a and not 1.0.0 ?
The first actually reads 1.0.0! Problem is, however, that tu8UVersion is not null-terminated, thus printf (not sscanf) prints beyound the field (doing so is undefined behaviour, however, as noted by sjsam) - which is immediately followed by tu8UCommit (does not necessarily have to be so, there could still be some fill bytes in between for alignment reasons!).
You need to either print 5 characters at most (%.5s in printf format string) or leave place for terminating the tu8UVersion with 0, as proposed in a comment already.
Something similar could have happened with your buffers, too. You are lucky that they appearently have been initialized to 0 already (probably because of compiled as debug version), which again does not necessarily have to happen. So with bad luck, you could have printed the whole rest of buf1 (having been left at garbage) and even beyond.
Why the first vers is equals to 1.0.09abc12345a and not 1.0.0 ?
Remember that you have
typedef struct vers
{
char tu8UVersion[5];
char tu8UCommit[32];
}tst_prg_versions;
I guess, there is a good chance the memory for tu8UVersion and tu8UCommit is contiguous. Since you have not null-terminated tu8UVersion when you do :
printf("vers='%s'\n", lstVer.tu8UVersion);
it goes on to print tu8UCommit and it stops because tu8UCommit is null terminated.
While sscanf seem the most sensible solution here you could also introduce some formatting :
char tu8UVersion[32];
/* version number can't get too big.
* So the first step is do allocated a
* reasonably - but not too - big size for it.
* So that you can be sure there are few empty bytes at the end.
*/
and then use a function to sanitize a string :
char* sanitized(char* ptr)
{
if(ptr[strlen(ptr)]!='\0') // include string.h for strlen
ptr[strlen(ptr)]='\0';
return ptr;
}
and print it like :
printf("vers='%s'\n", sanitized(lstVer.tu8UVersion));
Your problem has already been identified in the comments: You don't leave space for the terminating null character and the two strings are run together.
If you want to scan a version whose size you don't know beforehand, you can limit the characters to scan to decimal digits and points with %[.-9] or to everything except a hyphen with %[^-]. (The %[...] format is like %s, except that you must provide a list of valid characters in the brackets. A caret as first letter means that the string is made up of characters that are not listed. In other words, %s is short for %[^ \t\n]
When you scan a string, you should test the return value of sscanf to be sure that all items have been scanned correctly and contain valid values.
Here's a variant that scans version numbers of up to 11 letters:
#include <stdlib.h>
#include <stdio.h>
typedef struct vers
{
char tu8UVersion[12];
char tu8UCommit[32];
} tst_prg_versions;
int main(int argc, char **argv)
{
tst_prg_versions lstVer;
char str[] = "BOARD-VERS-v1.0.0-git+9abc12345a";
int n;
n = sscanf(str, "BOARD-VERS-v%11[^-]-git+%s",
lstVer.tu8UVersion, lstVer.tu8UCommit);
if (n == 2) {
printf("vers='%s'\n", lstVer.tu8UVersion);
printf("commit='%s'\n", lstVer.tu8UCommit);
} else {
puts("Parse error.");
}
return 0;
}

Evaluating type identifiers (%d) in strings, in C

I am working on Mac OSX and using bash as my shell. I am working in C and I am trying to create a file that will renumber files. The important part of my code is as follows:
int i;
for (i=0; i<numberOfFiles; i++) {
strcpy(fileName,""); //Set to Null
char append[formatLength]; //String being appended
sprintf(append,"%%0%dd", formatLength); //example output: %04d
strcat(fileName,filePrefix); //Attached Prefix
strcat(fileName,append); //Attaches appended part
//Missing code: Part which equvaluates %04d as int i, such as 0023.
}
This gets me the correct string format I am looking for (say formatLength=4): filePrefix+%04d. However, now I need to evaluate the %04d in the string and evaluate it as i, so that the files look like: file0001, file0002, etc.
Would anyone have any ideas. Thanks for your help.
Use the string you created with snprintf() as the format string for the next call to snprintf().
int formatLength = /* some input */;
char filePrefix[FILEPREFIX_LEN]; // assigned by some input
const int FILENAME_LEN = strlen(filePrefix) + formatLength + 1; // +1 for terminating '\0'
char fileName[FILENAME_LEN];
int i;
for (i=0; i<numberOfFiles; i++) {
char temp[TEMPLATE_LEN]; // where TEMPLATE_LEN >= FILEPREFIX_LEN + 3 + number of characters in the decimal representation of formatLength
snprintf(temp, TEMPLATE_LEN, "%s%%0%dd", filePrefix, formatLength);
// error check snprintf here, in case the destination buffer was not large enough
snprintf(fileName, FILENAME_LEN, temp, i);
// error check snprintf here, in case the destination buffer was not large enough
// use fileName
}
So if your filePrefix = "file" then you'd get fileName = "file0001", "file0002", "file0003", and so on...
Although a lot of this work isn't actually dependant on i so you could move it outside the loop, like this:
int formatLength = /* some input */;
char filePrefix[FILEPREFIX_LEN]; // assigned by some input
const int FILENAME_LEN = strlen(filePrefix) + formatLength + 1; // +1 for terminating '\0'
char fileName[FILENAME_LEN];
char temp[TEMPLATE_LEN]; // where TEMPLATE_LEN >= FILEPREFIX_LEN + 3 + number of characters in the decimal representation of formatLength
snprintf(temp, TEMPLATE_LEN, "%s%%0%dd", filePrefix, formatLength);
// error check snprintf here, in case the destination buffer was not large enough
int i;
for (i=0; i<numberOfFiles; i++) {
snprintf(fileName, FILENAME_LEN, temp, i);
// error check snprintf here, in case the destination buffer was not large enough
// use fileName
}
In these cases, your temp (short for "template", not "temporary") is going to be "prefix%04d" (e.g., for a prefixLength of 4 and filePrefix of "prefix"). You need to take care, then, that your filePrefix does not contain any characters that have special meaning to the printf family of functions. If you know a priori that it won't, then you're good to go.
However, if it's possible it will, then you need to do one of two things. You can process the filePrefix before you use it by escaping all the special characters. Or you can change your snprintf() calls to something like these:
snprintf(temp, TEMPLATE_LEN, "%%s%%0%dd", formatLength);
// other stuff...
snprintf(fileName, FILENAME_LEN, temp, filePrefix, formatLength);
Note the extra % at the beginning of the first snprintf(). This makes the template pattern "%s%04d" (e.g., for a prefixLength of 4), and then you add the filePrefix on the second call so that it's contents are not part of the pattern string in the second call.
If I understand your question correctly, you should be able to say
char result[(sizeof filePrefix/sizeof (char)) + formatLength];
sprintf(result, fileName, i);
since fileName looks something like "filePrefix%04d". Your desired filename will be then stored in result. I would not recommend re-storing it in fileNameby saying sprintf(fileName, fileName, i) because fileName may be too small (for example, when formatLength = 9).
Note that you need (sizeof filePrefix/sizeof (char)) to find the size of filePrefix (which is likely also char*), and then you add formatLength to see how many more chars you need after that
You can build a format string then use that as a format string for another formatter call. Note they the prefix and number format specifier can be built into a single string - no need for strcat calls.
Given:
char format_specifier[256] ;
then the loop code in your example can be replaced with:
snprintf( format_specifier,
sizeof( format_specifier),
"%s%%0%dd",
filePrefix,
formatLength ) ; // Create format string "<filePrefix>%0<formatLength>",
// eg. "file%04d"
snprintf( fileName, // Where the filename will be built
sizeof(fileName), // The length of the filename buffer
format_specifier, // The previously built format string
i ) ; // The file number.
I have assumed above that fileName is an array, if it is a pointer to an array, then sizeof(fileName) will be incorrect. Of course if you choose to use sprintf rather than snprintf it is academic.
sprintf(fileNameString, fileName, i); // I think you mean this, but use snprintf()
You are almost there
// This line could be done before the loop
sprintf(append,"%%0%dd", formatLength); //example output: %04d
// Location to store number
char NumBuffer[20];
// Form textual version of number
sprintf(NumBuffer, append, i);
strcat(fileName,filePrefix); //Attached Prefix
strcat(fileName,NumBuffer); //Attaches appended part

Resources