Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CS283
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Charles Barnwell
CS283
Commits
8de727c4
Commit
8de727c4
authored
3 months ago
by
Charles Barnwell
Browse files
Options
Downloads
Patches
Plain Diff
Upload New File
parent
0f53093d
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
1-C-Refresher/stringfun.c
+333
-0
333 additions, 0 deletions
1-C-Refresher/stringfun.c
with
333 additions
and
0 deletions
1-C-Refresher/stringfun.c
0 → 100644
+
333
−
0
View file @
8de727c4
#include
<stdio.h>
#include
<string.h>
#include
<stdlib.h>
#include
<stdbool.h>
#define BUFFER_SZ 50
//prototypes
void
usage
(
char
*
);
void
print_buff
(
char
*
,
int
);
int
setup_buff
(
char
*
,
char
*
,
int
);
//prototypes for functions to handle required functionality
int
count_words
(
char
*
,
int
,
int
);
//add additional prototypes here
int
reverse_str
(
char
*
,
int
,
int
);
int
find_word
(
char
*
,
char
*
);
int
replace_word
(
char
*
,
char
*
,
char
*
,
int
,
int
);
int
print_words
(
char
*
,
int
,
int
);
int
setup_buff
(
char
*
buff
,
char
*
user_str
,
int
len
){
//TODO: #4: Implement the setup buff as per the directions
if
(
len
>
BUFFER_SZ
)
return
-
1
;
int
str_len
=
0
;
char
*
temp
=
buff
;
while
(
*
user_str
==
' '
)
buff
++
;
// skip leading spaces
while
(
*
user_str
!=
'\0'
&&
str_len
<
len
-
1
)
{
if
(
*
user_str
==
' '
&&
(
*
(
user_str
+
1
)
==
' '
||
*
(
user_str
+
1
)
==
'\0'
))
{
user_str
++
;
continue
;
}
*
temp
=
*
user_str
;
temp
++
;
user_str
++
;
str_len
++
;
}
*
temp
=
'\0'
;
return
str_len
;
}
void
print_buff
(
char
*
buff
,
int
len
){
printf
(
"Buffer: "
);
for
(
int
i
=
0
;
i
<
len
;
i
++
){
putchar
(
*
(
buff
+
i
));
}
putchar
(
'\n'
);
}
void
usage
(
char
*
exename
){
printf
(
"usage: %s [-h|c|r|w|x]
\"
string
\"
[other args]
\n
"
,
exename
);
}
int
count_words
(
char
*
buff
,
int
len
,
int
str_len
){
if
(
len
<
str_len
||
buff
==
NULL
)
return
-
1
;
int
ctr
=
0
;
bool
counting
=
false
;
while
(
*
buff
!=
'\0'
)
{
if
(
*
buff
!=
' '
&&
!
counting
)
{
counting
=
true
;
ctr
++
;
}
else
if
(
*
buff
==
' '
&&
counting
)
counting
=
false
;
buff
++
;
}
return
ctr
;
}
//ADD OTHER HELPER FUNCTIONS HERE FOR OTHER REQUIRED PROGRAM OPTIONS
int
reverse_str
(
char
*
buff
,
int
buff_len
,
int
str_len
)
{
if
(
buff_len
==
0
)
{
printf
(
"Empty String"
);
return
-
1
;
}
char
*
end
=
buff
;
while
(
*
end
!=
'\0'
)
end
++
;
end
--
;
char
*
rev_str
=
malloc
(
sizeof
(
char
)
*
(
str_len
+
1
));
if
(
rev_str
==
NULL
)
{
printf
(
"Memory allocation error
\n
"
);
return
-
1
;
}
char
*
temp
=
rev_str
;
while
(
end
>=
buff
)
{
*
temp
=
*
end
;
temp
++
;
end
--
;
}
*
temp
=
'\0'
;
printf
(
"Reversed String: %s
\n
"
,
rev_str
);
free
(
rev_str
);
return
0
;
}
int
find_word
(
char
*
buff
,
char
*
word
)
{
const
char
*
b
=
buff
;
const
char
*
w
=
word
;
int
index
=
0
;
// to track the starting index of the word
while
(
*
b
!=
'\0'
)
{
if
(
*
b
==
*
w
)
{
const
char
*
b_temp
=
b
;
const
char
*
w_temp
=
w
;
while
(
*
w_temp
!=
'\0'
&&
*
b_temp
==
*
w_temp
)
{
b_temp
++
;
w_temp
++
;
}
if
(
*
w_temp
==
'\0'
)
{
return
index
;
}
}
b
++
;
index
++
;
}
return
-
1
;
// word not found
}
int
replace_word
(
char
*
buff
,
char
*
word
,
char
*
replacement
,
int
buff_len
,
int
str_len
)
{
if
(
str_len
>
buff_len
||
str_len
==
0
)
return
-
2
;
// invalid input
int
index
=
find_word
(
buff
,
word
);
if
(
index
==
-
1
)
return
-
1
;
// word doesn't exist in string
int
word_len
=
0
;
while
(
word
[
word_len
]
!=
'\0'
)
word_len
++
;
int
replacement_len
=
0
;
while
(
replacement
[
replacement_len
]
!=
'\0'
)
replacement_len
++
;
if
(
str_len
-
word_len
+
replacement_len
>
buff_len
)
return
-
3
;
// replcaement exceeds buffer size
if
(
replacement_len
!=
word_len
)
{
char
*
end
=
buff
+
str_len
;
char
*
src
=
buff
+
index
+
word_len
;
char
*
dest
=
buff
+
index
+
replacement_len
;
if
(
replacement_len
>
word_len
)
{
while
(
end
>=
src
)
{
*
(
dest
--
)
=
*
(
end
--
);
}
}
else
{
while
(
*
src
!=
'\0'
)
{
*
(
dest
++
)
=
*
(
src
++
);
}
*
dest
=
'\0'
;
}
}
char
*
replace_ptr
=
buff
+
index
;
const
char
*
replacement_ptr
=
replacement
;
while
(
*
replacement_ptr
!=
'\0'
)
*
replace_ptr
++
=
*
replacement_ptr
++
;
printf
(
"Modified String: %s
\n
"
,
buff
);
return
0
;
}
int
print_words
(
char
*
buff
,
int
buff_len
,
int
str_len
)
{
if
(
str_len
>
buff_len
)
return
-
1
;
if
(
str_len
==
0
)
return
0
;
int
word_count
=
0
;
// to start
int
char_ctr
=
0
;
// length of the current word
bool
at_start
=
true
;
// if we are currently counting words
printf
(
"Word Print
\n
----------
\n
"
);
while
(
*
buff
!=
'\0'
)
{
if
(
*
buff
!=
' '
&&
at_start
)
{
word_count
++
;
at_start
=
false
;
// we are processing a new word
printf
(
"%d. "
,
word_count
);
}
if
(
*
buff
==
' '
&&
!
at_start
)
{
// we hit the end of the word
printf
(
" (%d)
\n
"
,
char_ctr
);
// length of the current word
char_ctr
=
0
;
// start count for the next word
at_start
=
true
;
// we are starting a new word
}
else
{
// we are just encountering a normal character
printf
(
"%c"
,
*
buff
);
// current character
char_ctr
++
;
// add to length of current string
}
buff
++
;
}
if
(
!
at_start
)
printf
(
" (%d)
\n
"
,
char_ctr
);
// this is for the last word
return
word_count
;
// hold total number of words
}
int
main
(
int
argc
,
char
*
argv
[]){
char
*
buff
;
//placehoder for the internal buffer
char
*
input_string
;
//holds the string provided by the user on cmd line
char
opt
;
//used to capture user option from cmd line
int
rc
;
//used for return codes
int
user_str_len
;
//length of user supplied string
//TODO: #1. WHY IS THIS SAFE, aka what if argv[1] does not exist?
/*
Since argv[0] is the name of the executable, argv[1] is the first parameter used as input.
If argv[1] doesn't exist, then the program could run into problems. The code below prevents those.
*/
if
((
argc
<
2
)
||
(
*
argv
[
1
]
!=
'-'
)){
usage
(
argv
[
0
]);
exit
(
1
);
}
opt
=
(
char
)
*
(
argv
[
1
]
+
1
);
//get the option flag
//handle the help flag and then exit normally
if
(
opt
==
'h'
){
usage
(
argv
[
0
]);
exit
(
0
);
}
//WE NOW WILL HANDLE THE REQUIRED OPERATIONS
//TODO: #2 Document the purpose of the if statement below
/*
If the number of arguments is less than 3 (including the executable's name),
print the usage of the program (the possible flags and input), then exit.
*/
if
(
argc
<
3
){
usage
(
argv
[
0
]);
exit
(
1
);
}
input_string
=
argv
[
2
];
//capture the user input string
char
*
choice
;
char
*
replacement
;
if
(
opt
==
'x'
)
{
if
(
argc
==
5
)
{
choice
=
argv
[
3
];
replacement
=
argv
[
4
];
}
else
{
printf
(
"Error: invalid number of arguments"
);
exit
(
2
);
}
}
//TODO: #3 Allocate space for the buffer using malloc and
// handle error if malloc fails by exiting with a
// return code of 99
buff
=
malloc
(
sizeof
(
char
)
*
BUFFER_SZ
);
if
(
buff
==
NULL
)
{
printf
(
"Error setting up buffer"
);
exit
(
99
);
}
user_str_len
=
setup_buff
(
buff
,
input_string
,
BUFFER_SZ
);
//see todos
if
(
user_str_len
<
0
){
printf
(
"Error setting up buffer, error = %d"
,
user_str_len
);
exit
(
2
);
}
switch
(
opt
){
case
'c'
:
rc
=
count_words
(
buff
,
BUFFER_SZ
,
user_str_len
);
//you need to implement
if
(
rc
<
0
){
printf
(
"Error counting words, rc = %d"
,
rc
);
exit
(
2
);
}
printf
(
"Word Count: %d
\n
"
,
rc
);
break
;
//TODO: #5 Implement the other cases for 'r' and 'w' by extending
// the case statement options
case
'r'
:
rc
=
reverse_str
(
buff
,
BUFFER_SZ
,
user_str_len
);
if
(
rc
<
0
)
{
printf
(
"Error reversing words, rc = %d"
,
rc
);
exit
(
2
);
}
break
;
case
'w'
:
rc
=
print_words
(
buff
,
BUFFER_SZ
,
user_str_len
);
if
(
rc
<
0
)
{
printf
(
"Error printing words, rc = %d"
,
rc
);
exit
(
2
);
}
break
;
case
'x'
:
rc
=
replace_word
(
buff
,
choice
,
replacement
,
BUFFER_SZ
,
user_str_len
);
if
(
rc
<
0
)
{
printf
(
"Error replacing words, rc = %d"
,
rc
);
exit
(
2
);
}
break
;
default:
usage
(
argv
[
0
]);
exit
(
1
);
}
//TODO: #6 Dont forget to free your buffer before exiting
print_buff
(
buff
,
BUFFER_SZ
);
free
(
buff
);
exit
(
0
);
}
//TODO: #7 Notice all of the helper functions provided in the
// starter take both the buffer as well as the length. Why
// do you think providing both the pointer and the length
// is a good practice, after all we know from main() that
// the buff variable will have exactly 50 bytes?
//
// In a case where the global BUFFER_SZ variable is changed,
// you don't want the behavior of each of the functions to
// to be affacted negatively. Providing both the pointer to
// the buffer and the length is good so that the length is
// never in question for any individual function.
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment