Skip to content

Instantly share code, notes, and snippets.

@oktal
Last active December 23, 2015 15:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oktal/6656683 to your computer and use it in GitHub Desktop.
Save oktal/6656683 to your computer and use it in GitHub Desktop.
String manipulation in C
#include "string.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h> /* DEBUG */
static string_err string_enlarge(String *this, size_t add)
{
string_err err = STRING_ERR_OK;
size_t size = this->size;
size_t oldsize = this->size;
size_t newsize = size + add;
while (size < newsize)
{
size *= 2;
}
if (this != NULL)
{
this->s = realloc(this->s, size);
if (this->s != NULL)
{
memset(this->s + oldsize, 0, size - oldsize); /* setting underminated memory to 0 */
this->size = size;
}
else
{
err = STRING_ERR_MEMORY;
}
}
else
{
err = STRING_ERR_NULL;
}
return err;
}
static void string_purge(void)
{
int c;
while ((c = fgetc(stdin)) != '\n' && c != EOF)
{
}
}
String *new_string(void)
{
String *this = malloc(sizeof *this);
if (this != NULL)
{
this->size = 1;
this->index = 0;
this->s = malloc(1);
if (this->s != NULL)
{
this->s[0] = 0;
}
}
return this;
}
string_err string_add_char(String *this, int const c)
{
string_err err = STRING_ERR_OK;
if (this != NULL)
{
if (this->s != NULL)
{
size_t const s_len = 1; /* character's len */
if (this->index + s_len >= this->size)
{
err = string_enlarge(this, s_len);
}
if (err == STRING_ERR_OK)
{
this->s[this->index++] = c;
this->s[this->index] = 0;
}
}
}
else
{
err = STRING_ERR_NULL;
}
return err;
}
string_err string_add_str(String *this, char const *s)
{
string_err err = STRING_ERR_NULL;
if (this != NULL)
{
if (this->s != NULL && s != NULL)
{
size_t const s_len = strlen(s);
if (this->index + s_len >= this->size)
{
err = string_enlarge(this, s_len);
}
if (err == STRING_ERR_OK)
{
memcpy(this->s + this->index, s, s_len);
this->index += s_len;
}
}
}
else
{
err = STRING_ERR_NULL;
}
return err;
}
void string_puts(String *this)
{
if (this != NULL && this->s != NULL)
{
puts(this->s);
}
}
string_err string_gets(String *this)
{
string_err err = STRING_ERR_OK;
if (this != NULL && this->s != NULL)
{
size_t i = 0;
int c;
while ((c = fgetc(stdin)) != '\n' && c != EOF && err == STRING_ERR_OK)
{
if (i >= this->size)
{
err = string_enlarge(this, this->size * 2); /* growing by 2 */
}
if (err == STRING_ERR_OK)
{
this->s[this->index] = c;
this->index++;
}
i++;
}
this->s[this->index] = 0;
}
return err;
}
string_err string_ngets(String *this, size_t n)
{
string_err err = STRING_ERR_OK;
if (this != NULL && this->s != NULL)
{
size_t i = 0;
int c;
while ((c = fgetc(stdin)) != '\n' && c != EOF && err == STRING_ERR_OK)
{
if (i < n - 1)
{
if (i >= this->size)
{
err = string_enlarge(this, this->size * 2);
}
if (err == STRING_ERR_OK)
{
this->s[this->index] = c;
this->index++;
}
i++;
}
this->s[i] = 0;
}
}
return err;
}
char *string_str(String *this)
{
char *ret = NULL;
if (this != NULL)
{
ret = this->s;
}
return ret;
}
void string_clear(String *this)
{
if (this != NULL)
{
free(this->s), this->s = NULL;
this->index = this->size = 0;
}
}
void string_delete(String *this)
{
if (this != NULL)
{
free(this->s);
free(this);
}
}
#ifndef STRING_H_INCLUDED
#define STRING_H_INCLUDED
#include <stddef.h> /* size_t */
#include <string.h>
typedef struct string
{
size_t size;
size_t index;
char *s;
} String;
typedef enum
{
STRING_ERR_OK, STRING_ERR_MEMORY, STRING_ERR_NULL
} string_err;
String *new_string(void);
string_err string_add_char(String *this, int const c);
string_err string_add_str(String *this, char const *s);
void string_puts(String *this);
string_err string_gets(String *this);
string_err string_ngets(String *this, size_t n);
char *string_str(String *this);
void string_clear(String *this);
void string_delete(String *this);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment