Modestus Moon OS  R4
CS 450 project
string.c
Go to the documentation of this file.
1 #include <system.h>
2 #include <string.h>
3 
4 
10 int strlen(const char *s) // created by nick 1/23/17
11 {
12  int length = 0;
13  while(s[length] != '\0') {
14  length++;
15  }
16  //length++;
17  return length; // return length of string
18 }
19 
26 char* strcpy(char *s1, const char *s2)
27 {
28  char* s1Cpy = s1;
29  while(*s2 != '\0') {
30  *s1 = *s2;
31  s1++;
32  s2++;
33  }
34  if(*s2 == '\0') {
35 
36  *s1 = *s2;
37  }
38  return s1Cpy; // return pointer to destination string
39 }
40 
46 int atoi(const char *s)
47 {
48  int num = 0;
49 
50  if(!s)
51  {
52  return 0;
53  }
54  while(*s==' '){ s++; }
55 
56  int isNeg = ( *s == '-');
57  if(isNeg || (*s == '+')){ s++; }
58  while((*s >= '0') && (*s <= '9' ))
59  {
60  num = (num*10) + (*s - '0');
61  s++;
62  }
63  if(isNeg)
64  {
65  num = num *(-1);
66  }
67 
68  return num; // return integer
69 }
70 
77 int strcmp(const char *s1, const char *s2)
78 {
79 
80  // Remarks:
81  // 1) If we made it to the end of both strings (i. e. our pointer points to a
82  // '\0' character), the function will return 0
83  // 2) If we didn't make it to the end of both strings, the function will
84  // return the difference of the characters at the first index of
85  // indifference.
86  int i = 0;
87  for(; (s1[i]) && (s2[i]) && (s1[i]==s2[i]); i++)
88  {
89  }
90 
91  return s1[i]-s2[i];
92 }
93 
94 
101 char* strcat(char *s1, const char *s2)
102 {
103  char *rc = s1;
104  if (*s1) while(*++s1);
105  while( (*s1++ = *s2++) );
106  return rc;
107 }
108 
114 int isspace(const char *c)
115 {
116  if (*c == ' ' ||
117  *c == '\n' ||
118  *c == '\r' ||
119  *c == '\f' ||
120  *c == '\t' ||
121  *c == '\v'){
122  return 1;
123  }
124  return 0;
125 }
126 
127 /*
128  Procedure..: memset
129  Description..: Set a region of memory.
130  Params..: s-destination, c-byte to write, n-count
131 */
139 void* memset(void *s, int c, size_t n)
140 {
141  unsigned char *p = (unsigned char *) s;
142  while(n--){
143  *p++ = (unsigned char) c;
144  }
145  return s;
146 }
147 
154 char* strtok(char *s1, const char *s2)
155 {
156  static char *tok_tmp = NULL;
157  const char *p = s2;
158 
159  //new string
160  if (s1!=NULL){
161  tok_tmp = s1;
162  }
163  //old string cont'd
164  else {
165  if (tok_tmp==NULL){
166  return NULL;
167  }
168  s1 = tok_tmp;
169  }
170 
171  //skip leading s2 characters
172  while ( *p && *s1 ){
173  if (*s1==*p){
174  ++s1;
175  p = s2;
176  continue;
177  }
178  ++p;
179  }
180 
181  //no more to parse
182  if (!*s1){
183  return (tok_tmp = NULL);
184  }
185 
186  //skip non-s2 characters
187  tok_tmp = s1;
188  while (*tok_tmp){
189  p = s2;
190  while (*p){
191  if (*tok_tmp==*p++){
192  *tok_tmp++ = '\0';
193  return s1;
194  }
195  }
196  ++tok_tmp;
197  }
198 
199  //end of string
200  tok_tmp = NULL;
201  return s1;
202 }
203 
204 
205 /* And finally....
206  For the brave ones! (Note: you'll need to add a prototype to string.h)
207  sprintf must work properly for the following types to receive extra credit:
208  1) characters
209  2) strings
210  3) signed integers
211  4) hexadecimal numbers may be useful
212  ...
213  \infty) Or feel free to completely implement sprintf
214  (Read the man Page: $ man sprintf)
215  int sprintf(char *str, const char *format, ...);
216 */
217 
218 // Created by nick 1/23/17, not finished yet
219 //modified by matt 1/25/17, finished
220 
229 int sprintf(char *str, int bufLength, const char *format, ...)
230 {
231 
232  if(!str || bufLength <= 0) {
233  return 0;
234  }
235 
236  arg_list list;
237  init_arg_list(list, format);
238 
239  int newStrIndex = 0;
240  int index, formatLength = strlen(format);
241  for(index = 0; format[index] != '\0' && index <= formatLength; index++)
242  {
243 
244  //flag is -1 until fulfilled, flag is 0 if not requested
245  if(format[index] == '%')
246  {
247  char leftJustified=0, alwaysAppendSign=0, subSignWithSpace=0, altForm=0, padWithZeros=0;
248  int minFieldWidth=0, precision=0;
249  (void)padWithZeros;
250  for(; !is_conversion_specifier(format[index]); index++)
251  {
252  if(format[index]=='\0')
253  {
254  return 0; //if we reach the end of the string, exit as the format is missing
255  }
256  if(!minFieldWidth && !precision)
257  {
258  switch(format[index])
259  {
260  case '-': leftJustified=1; break;
261  case '+': if(!leftJustified) {alwaysAppendSign=1;} break;
262  case ' ': if(!leftJustified && !alwaysAppendSign){subSignWithSpace=1;} break;
263  case '#': if(!leftJustified && !alwaysAppendSign && !subSignWithSpace) {altForm=1;} break;
264  case '0': if(!leftJustified && !alwaysAppendSign && !subSignWithSpace && !altForm){padWithZeros=1;} break;
265  }
266  }
267  if(format[index] == '.'){ precision = -1;}
268  if(isnum(format[index])) //implement the * modifier here
269  {
270  if(precision==-1)
271  {
272  precision = atoi(&format[index]);
273  }
274  else if(!minFieldWidth)
275  {
276  minFieldWidth = atoi(&format[index]);
277  }
278  }
279  }//finished parsing one conversion
280  //need to implement all modifiers
281  if(format[index]=='d')
282  {
283  newStrIndex += intToS((int*)next_arg_in_list(&list, &format[index], 0), &str[newStrIndex], bufLength-newStrIndex);
284  }
285  else if(format[index]=='c')
286  {
287  str[newStrIndex]= **((char**)next_arg_in_list(&list, &format[index], 0));
288  newStrIndex++;
289  }
290  else if(format[index]=='s')
291  {
292  char *strToCopy = *((char**)next_arg_in_list(&list, &format[index], 0));
293  int lengthOfCopy = strlen(strToCopy);
294  strcpy(&str[newStrIndex], strToCopy);
295  newStrIndex += lengthOfCopy;
296  }
297  }
298  else
299  {
300  str[newStrIndex] = format[index];
301  newStrIndex++;
302  }
303  }
304  str[newStrIndex]=0;
305  return newStrIndex;
306 }
307 
308 //created by matt 1/25/17
309 //returns number of characters written
317 int intToS(const int * const i, char *buf, int bufLength)
318 {
319  if(!buf)
320  {
321  return 0;
322  }
323 
324  int cpy=*i;
325  int length = 1;
326  if(*i < 0)
327  {
328  cpy*=-1;
329  length++;
330  }
331 
332  do{
333  length++;
334  }while((cpy/=10)); //find total length of string
335 
336  if(bufLength<length+1) //if the bufLength is less than the length+null term, return 0
337  {
338  return 0;
339  }
340 
341  cpy=(*i<0)?(*i) * -1: *i; //reset val copy
342  length--;
343  buf[length]='\0'; //insert null terminator at end of string
344  length--;
345  for(; length >= 0; length--) //convert int to char and copy into buffer backwards
346  {
347  buf[length] = cpy%10 + '0';
348  cpy/=10;
349  }
350  if(*i<0)
351  {
352  buf[0]='-';
353  }
354 
355  return strlen(buf);
356 }
357 
364 {
365  switch(c)
366  {
367  case 'c':
368  case 's':
369  case 'd': case 'i':
370  case 'u': case 'o': case 'x': case 'X':
371  case 'f': case 'F': case 'e': case 'E': case 'a': case'A': case 'g': case 'G':
372  case 'p':
373  return c;
374 
375  default: return 0;
376  }
377  return 0;
378 }
379 
385 inline int isnum(const char c)
386 {
387  return ((c >= '0') && (c <= '9'));
388 }
389 
390 
391 
void * memset(void *s, int c, size_t n)
memset Set a region of memory.
Definition: string.c:139
int intToS(const int *const i, char *buf, int bufLength)
intToS converts a signed integer to string
Definition: string.c:317
int sprintf(char *str, int bufLength, const char *format,...)
sprintf print with format to specified string buffer
Definition: string.c:229
char * strcat(char *s1, const char *s2)
strcat concatenates the contents of one string onto another.
Definition: string.c:101
int atoi(const char *s)
atoi converts and ASCII string to an integer
Definition: string.c:46
#define init_arg_list(argList, argBeforeEllipses)
implemented in macro because there are no templates in C
Definition: arg_list.h:25
#define NULL
Definition: system.h:4
char is_conversion_specifier(char c)
is_conversion_specifier checks to see if the character is one of the standard printf formats ...
Definition: string.c:363
#define arg_list
Definition: arg_list.h:19
int strlen(const char *s)
strlen returns the length of a string
Definition: string.c:10
char * strtok(char *s1, const char *s2)
strtok Split string into tokens.
Definition: string.c:154
int strcmp(const char *s1, const char *s2)
strcmp compares two strings.
Definition: string.c:77
int isnum(const char c)
isnum inline helper function to check if a character is represents an ascii number ...
Definition: string.c:385
int isspace(const char *c)
isspace Determines if a character is a whitespace.
Definition: string.c:114
char * strcpy(char *s1, const char *s2)
strcpy copies one string to another string
Definition: string.c:26