Thread: Clarification with C-style Strings

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    7

    Clarification with C-style Strings

    I've managed to load all of the text from a file into a single string. But I'm not sure if the way I've handled it is very safe, or very memory efficient. I'm still learning how all this stuff works.

    Code:
    ...
    
    while((nextChar = fgetc(file)) != EOF)
    {
       fileData = strConcat(fileData, (char *)&nextChar);
    }
    ...
    
    char *strConcat(char *str1, char *str2)
    {
       size_t size = strlen(str1) + strlen(str2) + 1;
       char *newStr = (char *)malloc(size);
    
       sprintf_s(newStr, size, "%s%s", str1, str2);
    
       return newStr; 
    }
    I'm mostly worried about my use of malloc. But everything seemed to be working ok so I moved on and then I attempted to write some code to search through this char array for specific characters.

    Code:
    for (i = 0; i < strlen(fileData); i++)
    {
       if (*(fileData + i) == '\n')
          printf("New line at: %i\n", i);
    }
    And this seemed to have worked correctly. What I want to do now is assign a char pointer to the start character of each new line. But I can't seem to figure out how to do it. I'll need a dynamically sized array but I can't work out how to make one.

  2. #2
    Registered User
    Join Date
    Sep 2008
    Location
    California
    Posts
    19
    One way you may want to think about is using pointers to pointers (**char) which point at the elements in the string array which point to the newline characters. This would make it pretty easy to access, and then continue to access the elements in the next line.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Posts
    7
    I've sort of got it working. Here's the code I have:

    Code:
    // Includes
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // Prototypes
    char *strConcat(char *str1, char *str2);
    
    // Main entry point
    int main(int argc, char *argv[])
    {
    	char *fileData = "";
    	char **lineData;
    	int nextChar, lineCount = 0, i;
    	FILE *file;
    
    	if (argc != 2)
    	{
    		printf("Usage: &#37;s filename", argv[0]);
    		return 0;
    	}
    
    	file = fopen(argv[1], "r");
    
    	if (file == 0)
    	{
    		printf("File not found!");
    	}
    	else
    	{
    		while((nextChar = fgetc(file)) != EOF)
    		{
    			if (nextChar == '\n')
    				lineCount++;
    			fileData = strConcat(fileData, (char *)&nextChar);
    		}
    	}
    
    	fclose(file);
    
    	printf("%s\n\n", fileData);
    
    	lineData = (char **)malloc(sizeof(char) * lineCount);
    	lineCount = 1;
    
    	lineData = &fileData;
    
    	for (i = 0; i < strlen(fileData); i++)
    	{
    		if (*(fileData + i) == '\n')
    		{
    			*(*lineData + lineCount) = *(fileData + i + 1);
    			lineCount++;
    		}
    	}
    
    	for (i = 0; i < lineCount; i++)
    	{
    		printf("Line: %i - Char: %c\n", i, *(*lineData + i));
    	}
    
    	getchar();
    
    	return 0;
    }
    
    char *strConcat(char *str1, char *str2)
    {
    	size_t size = strlen(str1) + strlen(str2) + 1;
    	char *newStr = (char *)malloc(sizeof(char) * size);
    
    	sprintf_s(newStr, size, "%s%s", str1, str2);
    
    	return newStr; 
    }
    There seems to be some overwriting in data. When I print out the fileData string at the very end, there's some new characters in it. Here's my test file data.

    Code:
    _                 <
     _ $33>100>_   114^
     _<72<101<<108>^
    _.          /^/<111>\87\>\32\>
    &{{{{{{{{{{{{#
    , Output: Hello World!
    Last edited by StapleGun; 10-30-2008 at 06:31 PM.

  4. #4
    Registered User
    Join Date
    Jan 2008
    Posts
    290
    1)
    A pointer to a character is NOT a string. Repeat several times until you understand. You can't just take a pointer to the character you received from fgetc(), pass it to a string function (like strlen()), and expect it to work.

    2)
    Code:
    while((nextChar = fgetc(file)) != EOF)
    {
    	if (nextChar == '\n')
    		lineCount++;
    	fileData = strConcat(fileData, (char *)&nextChar);
    }
    You are leaking memory like crazy here. You don't even attempt to free the previous value of fileData before you overwrite it.

    Suggestion: Why don't you read the file line-by-line using fgets() instead? Oh, and there's no reason why you need to allocate a new chunk of memory every single time you concatenate a string. There's a strcat() function for a reason. Allocate a sufficiently large amount of memory to start with (say.. 500 chars or so), and realloc only when you need to.

  5. #5
    Registered User
    Join Date
    Oct 2008
    Posts
    7
    Thanks, that was exactly the kind of information I was after regarding my file reading and string concatenation.

    I fully understand that a pointer to a character is not a string. (How could I have possibly written (*(fileData + i) == '\n') if i didn't?) What am I meant to say? the 'fileData character pointer which is pointing to the first character of a string of characters all sequential in memory?'. I think 'fileData string' is a little easier to say and I'm quite sure most people here would understand the meaning of it.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    No one's complaining about fileData. We are complaining very strenuously about nextChar. nextChar is not null-terminated, which means you will get, on average, 2 billion extra characters after your character.

  7. #7
    Registered User
    Join Date
    Jan 2008
    Posts
    290
    I'm not sure what you're on about there in the second half of that post, but my first point was in regards to this:
    Code:
    ...
    		while((nextChar = fgetc(file)) != EOF)
    		{
    			if (nextChar == '\n')
    				lineCount++;
    			fileData = strConcat(fileData, (char *)&nextChar);
    		}
    ...
    char *strConcat(char *str1, char *str2)
    {
    	size_t size = strlen(str1) + strlen(str2) + 1; //str2 is not a string!
    	char *newStr = (char *)malloc(sizeof(char) * size);
    
    	sprintf_s(newStr, size, "%s%s", str1, str2); //str2 is still not a string
    
    	return newStr; 
    }
    It had nothing to do with anything you said.

    Is that clearer?

  8. #8
    Registered User
    Join Date
    Oct 2008
    Posts
    7
    Ah now I see what you're saying. But I'm not sure how I'd go about terminating that character? Haven't I declared nextChar int? As required by the function fgetc()?

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Since strConcat is your own concoction, you can just change it to take the second parameter as a char (and printf a %c, instead of a %s, and so on).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Concatenating C style Strings Question
    By bengreenwood in forum C++ Programming
    Replies: 3
    Last Post: 03-19-2009, 03:19 PM
  2. Converting C++ Style strings...
    By LightsOut06 in forum C++ Programming
    Replies: 10
    Last Post: 10-26-2005, 03:02 PM
  3. winsock, sending c++ style strings
    By b00l34n in forum Networking/Device Communication
    Replies: 17
    Last Post: 05-06-2004, 07:41 PM
  4. converting c style strings to c++ strings
    By fbplayr78 in forum C++ Programming
    Replies: 6
    Last Post: 04-14-2003, 03:13 AM
  5. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM