Unexpected characters at the end of char array - C - c

I know similar questions have been posted before but I haven't been able to solve the issue for my case.
I have the following C code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char textChars[4] = { 'A', 'B', 'C', 'D' };
char noMatchChars[4] = { '1', '2', '3', '4' };
int tLengths[5] = { 14, 142, 1414, 14142, 141420 };
int i,j;
for (i = 0; i < 1; i++)
{
char textString1[tLengths[i]+1];
char textString2[tLengths[i]+1];
char textString3[tLengths[i]+1];
char textString4[tLengths[i]+1];
for (j = 0; j < tLengths[i]; j++)
{
textString1[j] = textChars[0];
textString2[j] = textChars[1];
textString3[j] = textChars[2];
textString4[j] = textChars[3];
}
textString1[tLengths[i]] = '\0';
textString2[tLengths[i]] = '\0';
textString3[tLengths[i]] = '\0';
textString4[tLengths[i]] = '\0';
FILE *fp;
char filepathPattern[14];
char filepathText[11];
char iChar[1];
sprintf(iChar, "%d", i);
strcpy(filepathText, iChar);
strcat(filepathText, "_text1.txt");
fp = fopen(filepathText, "w");
fprintf(fp, textString1);
fclose(fp);
memset(filepathText,0,strlen(filepathText));
strcpy(filepathText, iChar);
strcat(filepathText, "_text2.txt");
fp = fopen(filepathText, "w");
fprintf(fp, textString2);
fclose(fp);
memset(filepathText,0,strlen(filepathText));
strcpy(filepathText, iChar);
strcat(filepathText, "_text3.txt");
fp = fopen(filepathText, "w");
fprintf(fp, textString3);
fclose(fp);
memset(filepathText,0,strlen(filepathText));
strcpy(filepathText, iChar);
strcat(filepathText, "_text4.txt");
fp = fopen(filepathText, "w");
fprintf(fp, textString4);
fclose(fp);
}
}
It works as expected for every string expect for textString4 which outputs as 14 'D's as expected followed by a random character and then 14 'C's (the previous string) for some reason but the other strings don't have this issue.
I assumed it was a memory issue but when I replaced
char textStringX[tLengths[i]+1];
with char *textStringX = malloc( sizeof(char) * ( tLengths[i] + 1 ) );
the result was identical.
I'm new to C so apologies if the solution to this is trivial.

The first issues are string related. The following lines:
char iChar[1];
sprintf(iChar, "%d", i);
Are a problem, in that you created a char array, iChar, with room for only one char, then in the very next line try to use a string function sprintf to place two chars into iChar: the value of i (0 at this point) and the NULL char. You need to create iChar with more space: i.e.
char iChar[3]; // will allow printing up to any two digit value + NULL.
Eg. zero would look like this: |0|\0|\0|
99 like this: |9|9|\0|
In C, without a NULL termination, you do not have a C string. The string functions will not work properly without a C string.
Because the write to iChar fails in the call above, the next lines in your code, also string functions always expect NULL terminated char arrays. anything else will cause them to fail:
strcpy(filepathText, iChar);
strcat(filepathText, "_text1.txt");
Because I do not know the contents of your text file, I cannot take your code beyond this. But address these string issues, then step through your code line by line. I believe most of the issues you cite will be addressed.

Related

Unable to free 2D string array, compiler not recognizing first 2 indices [duplicate]

This question already has answers here:
How can I correctly assign a new string value?
(4 answers)
Closed 3 months ago.
I am unable to free my 2D string array. It seems that it is unable to read the items in vars[0] and vars[1]. When I print the vars array I am able to print vars[0] and vars[1], however, I am unable to free them as the compiler does not recognize that there is any data in both indices.
I am using fscanf to read data from a text file. The file does not include '0' or '1'. I need to have '0' and '1' in the first 2 indices of the 2D string array. The data read from the input file consists of mainly strings. That is why I am using a 2D string array.
I am also reallocating the array as I will be adding more variables to the array as I progress through the file.
Is it how I am adding the '0' and '1' into the 2D array that is causing this problem?
int main(int argc, char **argv) {
FILE *fp = fopen(argv[1], "r");
int i;
char type[17];
int input, output;
// fscanf for input
fscanf(fp, "%s", type);
fscanf(fp, "%d", &input);
char **vars = malloc((input+2)*sizeof(char*));
for (i = 0; i < input; i++) {
if (i == 0) {
vars[0] = malloc(17*sizeof(char));
vars[0] = "0\0";
}
if (i == 1) {
vars[1] = malloc(17*sizeof(char));
vars[1] = "1\0";
}
vars[i+2] = malloc(17*sizeof(char));
fscanf(fp, "%16s", vars[i+2]);
}
fscanf(fp, "%s", type);
fscanf(fp, "%d", &output);
int length = output + input + 2;
vars = realloc(vars, length*sizeof(char *));
for (i = 0; i < output; i++) {
vars[i+input+2] = malloc(17*sizeof(char));
fscanf(fp, "%16s", vars[i+input+2]);
printf("vars: \t");
print2D(vars, (input+2));
for (i = 0; i < length; i++) {
free(vars[i]);
}
free(vars);
fclose(fp);
return EXIT_SUCCESS;
}
When I do not add '0' or '1' to the array, and read the first variable directly into vars[0] I do not get this problem.
However, I need to have '0' and '1' be in their respective spots as I will need to retrieve the respective values as I lookup the index number for each variable.
For instance:
vars = {0, 1, a, b, c, d};
indx = {0, 1, 2, 3, 4, 5};
Your problem is
vars[0] = malloc(17*sizeof(char));
vars[0] = "0\0";
malloc returns a memory block at least size 17 (but you never check). Then you immediately lose your pointer to that block by pointing var[0] to the string literal "0\0" (this also creates a memory leak since you lose your pointer to the memory malloc returned). This is not the correct way to assign a string, use strcpy instead:
#include <string.h>
...
vars[0] = malloc(17*sizeof(char));
if (vars[0] == NULL)
{
// handle out of mem error how you want
}
else
{
strcpy(vars[0], "0\0");
}
And the same for every other place you're doing this.
You should also check that you successfully open your file before using the file pointer:
FILE *fp = fopen(argv[1], "r");
if (fp != NULL)
{
....
Finally, take heed of Barmar's comment. I generally try to answer with as few modifications to the OP as possible, but he is 100% correct in that you don't need to add your own NUL terminator in a string literal, the compiler will do that for you. For example:
char* str1 = "foo"; // this creates the array { 'f', 'o', 'o', '\0' }
// which is 4 long and makes str1 point to it.
char* str2 = "foo\0"; // creates the array { 'f', 'o', 'o'. '\0', '\0' }
// which is 5 long. The manual '\0' isn't needed.

when reading strings from an input file into a 2d array how do you substitute \n with \0, i.e extra line of garbage is being printed

I have this code to scan the strings from a given .txt file into an array:
void readSentences(char inputFilePath[], char inputSentences[][MAX_CHAR]) {
const char *INPUT_FILE_PATH = inputFilePath;
FILE *fp = fopen(INPUT_FILE_PATH, "r+");
int lineNum = 0;
while ( fgets( inputSentences[lineNum], sizeof(inputSentences[lineNum]), fp ) != NULL ) {
lineNum++;
}
fclose (fp);
}
The input file path is just a .txt file containing the names of countries, but when I try to print the array an extra line of nonsense is printed as below:
Hong Kong
Ecuador
Dominican Republic
Taiwan
Hong Kong
Taiwan
Australia
Hong Kong
Italy
Hong Kong
Ukraine
Republic of Irelandp7Þ♣'☻­§Ò♣'☻P☺þ♣'☻
Code that prints the array from main
int main() {
char array1[MAX_LINES][MAX_CHAR];
char array2[MAX_LINES][MAX_CHAR];
readSentences("..//inputFiles/input1.txt", array1);
readSentences("..//inputFiles/input2.txt", array2);
for (int i = 0; i < MAX_LINES; i++) {
printf("%s", array2[i]);
}
The arrays array1 and array2 have not been initialized before they are passed to readSentences(). If readSentences reads less than MAX_LINES files, the unread rows of the array will still contain uninitialized junk. printf("%s", array2[i]); is printing that junk, leading to undefined behavior.
There are various ways to initialize the state of array1 and array2 to something sensible before passing them to readSentences().
Initialize the array contents in the declaration:
char array1[MAX_LINES][MAX_CHARS] = {0};
char array2[MAX_LINES][MAX_CHARS] = {0};
Clear the array contents with memset():
memset(array1, 0, sizeof array1);
memset(array2, 0, sizeof array2);
Set the array rows to empty strings with strcpy():
for (int i = 0; i < MAX_LINES; i++) {
strcpy(array1[i], "");
strcpy(array2[i], "");
}
Set the array rows to empty strings by assigning '\0' to the first element of each row:
for (int i = 0; i < MAX_LINES; i++) {
array1[i][0] = '\0';
array2[i][0] = '\0';
}
It would be better for readSentences() to return the number of lines:
char inputFilePath[], char inputSentences[][MAX_CHAR]) {
...
return numLines;
}
Then the loop in main() can print just the valid lines:
nlines2 = readSentences("..//inputFiles/input2.txt", array2);
for (int i = 0; i < nlines2; i++) {
printf("%s", array2[i]);
}
This has nothing to do with the title of the question, which is about substituting '\n' with '\0', but that was a red herring. If you want to do that anyway, the usual trick is to use strcspn to find the index of the '\n' character if it is present, or the index of the end of the string if not. Either way, the character at that index can be changed to '\0':
while ( fgets( inputSentences[lineNum], sizeof(inputSentences[lineNum]), fp ) != NULL ) {
char *s = inputSentences[lineNum]; /* saves typing :-) */
s[strcspn(s, "\n")] = '\0';
lineNum++;
}
You need to modify readSentences and return the actual number of lines read from the file, either via a return value, or via a pointer parameter and print only the number of lines actually read.
Not knowing how many lines have been read makes the reading completely usless. Whatever code needs to process the lines read for whatever purpuse must know the number of lines read.
Something like this:
void readSentences(char inputFilePath[], char inputSentences[][MAX_CHAR], int *nblines) {
const char* INPUT_FILE_PATH = inputFilePath;
FILE* fp = fopen(INPUT_FILE_PATH, "r+");
int lineNum = 0;
while (fgets(inputSentences[lineNum], sizeof(inputSentences[lineNum]), fp) != NULL) {
lineNum++;
}
fclose(fp);
*nblines = lineNum;
}
int main() {
char array1[MAX_LINES][MAX_CHAR];
int nblines1;
char array2[MAX_LINES][MAX_CHAR];
int nblines2;
readSentences("..//inputFiles/input1.txt", array1, &nblines1);
readSentences("..//inputFiles/input2.txt", array2, &nblines2);
for (int i = 0; i < nblines2; i++) {
printf("%s", array2[i]);
}
}
There is still room for further improvment:
you need to check if fopen fails and act accordingly.
if the number of liens in a file is greater than MAX_LINES, you're out of luck and your array index will go out of bounds and you'll get undefined behaviour.
the // in "..//inputFiles/.... should probably be /.

Read only alphabets of a txt file containg blankspaces and numbers as well in c

I have a question about reading names(alphabets) from a txt file(directory.txt) containing spaces as well as numbers. After that by dynamic memory allocate space.
Input File:
It has 50 names just given some for reference.
80043 CHEBIYYAM
80131 SHUKLA
80200 GANGARAPU
85400 GAURAV
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define telenum 50
char **readnames ( char fname[], int n )
{
FILE *fp;
int i, l;
char **A, buf[1024];
fp = (FILE *)fopen(fname,"r");
if (fp == NULL) {
fprintf(stderr, "Error: unable to open file...\n");
n = 0;
return NULL;
}
A = (char **)malloc((n) * sizeof(char *));
for (i=0; i<n; ++i) {
while (getc(fp) != '\n');
fscanf(fp, "%s", buf);
l = strlen(buf);
A[i] = (char *)malloc((l+1) * sizeof(char));
strcpy(A[i],buf);
}
fclose(fp);
return A;
}
void printnames ( char **A, int n )
{
int i;
for (i=0; i<n; ++i) {
printf("%s\n", A[i]);
free(A[i]);
}
free(A);
}
int main ()
{
char **names;
names = readnames("directory.txt",telenum);
printnames(names,telenum);
}
I am getting random output not the desired one.
Please help.
I could just answer this changing a lot of the original code, but I think that I'll help more if I give you some tips.
Maybe the most important: Name your variables, describe what they do. This will turn easier to find your bug, and the community understand you code! :-D
What is A, n, telenum, l? Will be easier to read your code if you write the meaning of them ;-)
In the for in readnames function. You have a while(getc(fp) != '\n')
When you call getc, you get one character of the file. When you run this line, you're saying to computer: "Hey, drop the line I read since the for loop started away, I don't need it!"
When you get one character of the file, the file offset will go to the next character to you read it, then... you're reading the first character, then the next character, and the next.... till it is a '\n'. And... losing where you were.
The fscanf with the %s is an insecure function and you would need to do some tricks to read the whole line if you want to.
I suggest you to change this:
while (getc(fp) != '\n');
fscanf(fp, "%s", buf);
for this:
// Read the full line (including the '\n')
fgets(buf, MAX_LINE_SIZE, fp);
Your buffer must be cleaned before you reuse it.
Let's imagine a pretty small buffer with 10 characters:
['\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0']
Then, you read one number (10) and a name (Emma):
['1', '0', ' ', 'E', 'm', 'm', 'a', '\n', '\0', '\0']
Nice! Now, you read a smaller number (5) and another name (Dix)
['5', ' ', 'D', 'i', 'x', '\n', 'a', '\n', '\0', '\0']
Yey! Now I have a lot of trash, and I have no idead what is the name I just read. Also, I have 2 lines \o/
To avoid this, always remember to overwrite your whole buffer with something (usually '\0')
You can do this overwrite including this line: memset(buf, '\0', MAX_LINE_SIZE)
After is all OK getting the whole line, you need to remove the '\n'. You can do this overwriting the character on strlen(buf) - 1. Remember to update the length of the buffer if you want to store it in some variable.
There was a lot of work till here, after getting the line, removing the \n and the whole stuff above, you'll get one string in format 1354564 SOMENAME (by the examples you gave).
Now its easy, you can use a sscanf and extract the info you need. And if you don't know how to do it, here is an easy to follow tutorial
And Now... the code (with a lot of prints and comments)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define telenum 50
#define MAX_LINE_SIZE 1024
void extractNameFromBuffer(char *buffer)
{
int trash;
char extractorBuffer[MAX_LINE_SIZE];
// Separate the string and throw the number away
sscanf(buffer, "%d %s", &trash, extractorBuffer);
// clear buffer to store the fresh-new name!
memset(buffer, '\0', MAX_LINE_SIZE);
// Now, store the gotten name into the buffer
memcpy(buffer, extractorBuffer, strlen(extractorBuffer));
}
char **readNames ( char fileName[], int amountOfLines )
{
FILE *fp = NULL;
int i = 0, lineLength = 0;
char **names, buffer[MAX_LINE_SIZE];
fp = fopen(fileName,"r");
if (fp == NULL) {
fprintf(stderr, "Error: unable to open file...\n");
return NULL;
}
names = (char **)malloc((amountOfLines) * sizeof(char *));
for(i=0; i<amountOfLines; i++) {
// Clean the buffer before read a new line
memset(buffer, '\0', MAX_LINE_SIZE);
// Read the complete line, including spaces and \n's
fgets(buffer, MAX_LINE_SIZE, fp);
// If read nothing this time
if(buffer[0] == '\0') {
printf("This line is blank or does not exist, trying next line\n");
} else {
// Calculate the lenth of the line (including \n and special/blank characters)
lineLength = strlen(buffer);
// Overwrite the \n with a \0, removing the \n of the buffer
buffer[lineLength - 1] = '\0';
// Here we have the "165156 SOMENAME" strings
// Separate name from number
extractNameFromBuffer(buffer);
// Here we have the "SOMENAME" string, already!
// Updates lineLength (now we don't have the \n)
lineLength = strlen(buffer);
// Allocate memory to hold the name
names[i] = (char *)malloc( (lineLength + 1) * sizeof(char) );
// Copy the name to the new memory space
strcpy(names[i], buffer);
}
}
fclose(fp);
return names;
}
void printNames ( char **names, int amountOfLines )
{
int i;
for (i=0; i<amountOfLines; i++) {
if(names[i] != NULL) {
printf("%s\n", names[i]);
free(names[i]);
} else {
printf("No names names[%d] space\n", i);
}
}
free(names);
}
int main ()
{
char **names = NULL;
names = readNames("directory.txt",telenum);
printNames(names,telenum);
}
With a file with exactly 50 lines, this the end of my output:
With a file with 48 lines (missing 2 lines from 50), this is the end of output, as expected:
Hope this helps! Have fun!

C remove special characters from string

I am very new to C, and I have created a function that removes special characters from a string and returns a new string (without the special characters).
At first glance, this seemed to be working well, I now need to run this function on the lines of a (huge) text file (1 Million sentences). After a few thousand lines/sentences (About 4,000) I get a seg fault.
I don't have much experience with memory allocation and strings in C, I have tried to figure out what the problem with my code is, unfortunately without any luck.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char *preproccessString(char *str) {
// Create a new string of the size of the input string, so this might be bigger than needed but should never be too small
char *result = malloc(sizeof(str));
// Array of allowed chars with a 0 on the end to know when the end of the array is reached, I don't know if there is a more elegant way to do this
// Changed from array to string for sake of simplicity
char *allowedCharsArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Initalize two integers
// i will be increased for every char in the string
int i = 0;
// j will be increased every time a new char is added to the result
int j = 0;
// Loop over the input string
while (str[i] != '\0') {
// l will be increased for every char in the allowed chars array
int l = 0;
// Loop over the chars in the allowed chars array
while (allowedCharsArray[l] != '\0') {
// If the char (From the input string) currently under consideration (index i) is present in the allowed chars array
if (allowedCharsArray[l] == toupper(str[i])) {
// Set char at index j of result string to uppercase version of char currently under consideration
result[j] = toupper(str[i]);
j++;
}
l++;
}
i++;
}
return result;
}
Here is the rest of the program, I think the problem is probably here.
int main(int argc, char *argv[]) {
char const * const fileName = argv[1];
FILE *file = fopen(fileName, "r");
char line[256];
while (fgets(line, sizeof(line), file)) {
printf("%s\n", preproccessString(line));
}
fclose(file);
return 0;
}
You have several problems.
You're not allocating enough space. sizeof(str) is the size of a pointer, not the length of the string. You need to use
char *result = malloc(strlen(str) + 1);
+ 1 is for the terminating null byte.
You didn't add a terminating null byte to the result string. Add
result[j] = '\0';
before return result;
Once you find that the character matches an allowed character, there's no need to keep looping through the rest of the allowed characters. Add break after j++.
Your main() function is never freeing the results of preprocessString(), so you might be running out of memory.
while (fgets(line, sizeof(line), file)) {
char *processed = preproccessString(line);
printf("%s\n", processed);
free(processed);
}
You could address most of these problems if you have the caller pass in the result string, instead of allocating it in the function. Just use two char[256] arrays in the main() function.
int main(int argc, char *argv[])
{
char const* const fileName = argv[1];
FILE* file = fopen(fileName, "r");
char line[256], processed[256];
while (fgets(line, sizeof(line), file)) {
processString(line, processed);
printf("%s\n", processed);
}
fclose(file);
return 0;
}
Then just change the function so that the parameters are:
void preprocessString(const char *str, char *result)
A good rule of thumb is to make sure there is one free for every malloc/calloc call.
Also, a good tool to keep note of for the future is Valgrind. It's very good at catching these kinds of errors.
There are some major issues in your code:
the amount of memory allocated is incorrect, sizeof(str) is the number of bytes in a pointer, not the length of the string it points to, which would also be incorrect. You should write char *result = malloc(strlen(str) + 1);
the memory allocated in preproccessString is never freed, causing memory leaks and potentially for the program to run out of memory on very large files.
you do not set a null terminator at the end of the result string
Lesser issues:
you do not check if filename was passed nor if fopen() succeeded.
there is a typo in preproccessString, it should be preprocessString
you could avoid memory allocation by passing a properly sized destination array.
you could use isalpha instead of testing every letter
you should cast the char values as unsigned char when passing them to toupper because char may be a signed type and toupper is undefined for negative values except EOF.
there are too many comments in your source file, most of which are obvious but make the code less readable.
Here is a modified version:
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
// transform the string in `str` into buffer dest, keeping only letters and uppercasing them.
char *preprocessString(char *dest, const char *str) {
int i, j;
for (i = j = 0; str[i] != '\0'; i++) {
if (isalpha((unsigned char)str[i])
dest[j++] = toupper((unsigned char)str[i]);
}
dest[j] = '\0';
return dest;
}
int main(int argc, char *argv[]) {
char line[256];
char dest[256];
char *filename;
FILE *file;
if (argc < 2) {
fprintf(stderr, "missing filename argument\n");
return 1;
}
filename = argv[1];
if ((file = fopen(filename, "r")) == NULL) {
fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
return 1;
}
while (fgets(line, sizeof(line), file)) {
printf("%s\n", preprocessString(dest, line));
}
fclose(file);
return 0;
}
The following proposed code:
cleanly compiles
performs the desired functionality
properly checks for errors
properly checks for length of input string parameter
makes use of characteristic of strchr() also checking the terminating NUL byte
limits scope of visibility of local variables
the calling function is expected to properly cleaning up by passing the returned value to free()
the calling function is expected to check the returned value for NULL
informs compiler the user knows and accepts when an implicit conversion is made.
moves allowedCharsArray to 'file static scope' so does not have to be re-initialized on each pass through the loop and marks as 'const' to help the compiler catch errors
and now the proposed code: (note: edited per comments)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
char *preproccessString(char *str)
{
// Create a new string of the size of the input string, so this might be bigger than needed but should never be too small
char *result = calloc( sizeof( char ), strlen(str)+1);
if( !result )
{
perror( "calloc failed" );
return NULL;
}
// Array of allowed chars
static const char *allowedCharsArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Loop over the input string
for( int j=0, i=0; str[i]; i++)
{
if( strchr( allowedCharsArray, (char)toupper( str[i] ) ) )
{
// Set char at index j of result string to uppercase version of char currently under consideration
result[j] = (char)toupper(str[i]);
j++;
}
}
return result;
}
I think the problem is you are using malloc which allocates memory from the heap and since you are calling this function again and again you are running out of memory.
To solve this issue you have to call the free() function on the pointer returned by your preprocessString function
In your main block
char *result=preprocessString(inputstring);
//Do whatever you want to do with this result
free(result);

fscanf() to read in only characters with no punctuation marks

I would like to read in some words (in this example first 20) from a text file (name specified as an argument in the command line). As the below code runs, I found it takes punctuation marks with characters too.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char * argv[]){
int wordCap = 20;
int wordc = 0;
char** ptr = (char **) calloc (wordCap, sizeof(char*));
FILE *myFile = fopen (argv[1], "r");
if (!myFile) return 1;
rewind(myFile);
for (wordc = 0; wordc < wordCap; wordc++){
ptr[wordc] = (char *)malloc(30 * sizeof( char ) );
fscanf(myFile, "%s", ptr[wordc]);
int length = strlen(ptr[wordc]);
ptr[wordc][length] = '\0';
printf("word[%d] is %s\n", wordc, ptr[wordc]);
}
return 0;
}
As I pass through the sentence: "Once when a Lion was asleep a little Mouse began running up and down upon him;", "him" will be followed with a semicolon.
I changed the fscanf() to be fscanf(myFile, "[a-z | A-Z]", ptr[wordc]);, it takes the whole sentence as a word.
How can I change it to make the correct output?
You could accept the semi-colon and then remove it latter, like so:
after you've stored the word in ptr[wordc]:
i = 0;
while (i < strlen(ptr[wordc]))
{
if (strchr(".;,!?", ptr[wordc][i])) //add any char you wanna delete to that string
memmove(&ptr[wordc][i], &ptr[wordc][i + 1], strlen(ptr[wordc]) - i);
else
i++;
}
if (strlen(ptr[wordc]) > 0) // to not print any word that was just punctuations beforehand
printf("word[%d] is %s\n", wordc, ptr[wordc]);
I haven't tested this code, so there might be a typo or something in it.
Alternatively you could switch
fscanf(myFile, "%s", ptr[wordc]);
for
fscanf(myFile, "%29[a-zA-Z]%*[^a-zA-Z]", ptr[wordc]);
to capture only letters. the 29 limits word size so you don't get overflow since you're allocating size for only 30 chars

Resources