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
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Adorn Binoy
cs283
Commits
19bbd273
Commit
19bbd273
authored
6 months ago
by
Adorn Binoy
Browse files
Options
Downloads
Patches
Plain Diff
First homework assignment
parent
67ed2676
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
1-C-Refresher/makefile
+20
-0
20 additions, 0 deletions
1-C-Refresher/makefile
1-C-Refresher/stringfun
+0
-0
0 additions, 0 deletions
1-C-Refresher/stringfun
1-C-Refresher/stringfun.c
+265
-0
265 additions, 0 deletions
1-C-Refresher/stringfun.c
with
285 additions
and
0 deletions
1-C-Refresher/makefile
0 → 100644
+
20
−
0
View file @
19bbd273
# Compiler settings
CC
=
gcc
CFLAGS
=
-Wall
-Wextra
-g
# Target executable name
TARGET
=
stringfun
# Default target
all
:
$(TARGET)
# Compile source to executable
$(TARGET)
:
stringfun.c
$(
CC
)
$(
CFLAGS
)
-o
$(
TARGET
)
$^
# Clean up build files
clean
:
rm
-f
$(
TARGET
)
# Phony targets
.PHONY
:
all clean
\ No newline at end of file
This diff is collapsed.
Click to expand it.
1-C-Refresher/stringfun
0 → 100755
+
0
−
0
View file @
19bbd273
File added
This diff is collapsed.
Click to expand it.
1-C-Refresher/stringfun.c
0 → 100644
+
265
−
0
View file @
19bbd273
#include
<stdio.h>
#include
<string.h>
#include
<stdlib.h>
#define BUFFER_SZ 50
//prototypes
void
usage
(
char
*
);
void
print_buff
(
char
*
,
int
);
int
setup_buff
(
char
*
,
char
*
,
int
);
int
count_words
(
char
*
,
int
,
int
);
// Implementatino of the setup buff as per the directions
int
setup_buff
(
char
*
buff
,
char
*
user_str
,
int
len
)
{
char
*
dest
=
buff
;
// Pointer to the buffer
char
prevChar
=
' '
;
// Tracks previous character for spaces
int
charCounter
=
0
;
// Number of characters processed
// Null check for input string
if
(
user_str
==
NULL
)
{
printf
(
"Error: Null input string.
\n
"
);
return
-
1
;
}
// Process user_str and fill the buffer
while
(
*
user_str
!=
'\0'
&&
charCounter
<
len
)
{
// Copy every nonwhite space character into internal buffer and updates variables
if
(
*
user_str
!=
' '
&&
*
user_str
!=
'\t'
)
{
*
dest
=
*
user_str
;
dest
++
;
charCounter
++
;
prevChar
=
*
user_str
;
}
// Checks for double space and replaces with single space
else
if
(
prevChar
!=
' '
)
{
*
dest
=
' '
;
dest
++
;
charCounter
++
;
prevChar
=
' '
;
}
// Increments input pointer to next memory location
user_str
++
;
}
// Checks for the user supplied string being too large (end never reached)
if
(
*
user_str
!=
'\0'
)
{
printf
(
"Error: Provided input string is too long.
\n
"
);
return
-
1
;
}
// Fill the rest of the buffer with dots
while
(
charCounter
<
len
)
{
*
dest
=
'.'
;
dest
++
;
charCounter
++
;
}
// If no errors, return the length of the user supplied string
return
charCounter
;
}
// Function to print the entire buffer
void
print_buff
(
char
*
buff
,
int
len
)
{
printf
(
"Buffer: %.*s
\n
"
,
len
,
buff
);
}
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
)
{
// Exit if string length greater than the buffer length
if
(
str_len
>
len
)
{
return
-
1
;
}
// Exit if the string is empty
if
(
str_len
==
0
)
{
return
0
;
}
int
totalWords
=
0
;
// Loops through the buffer and updates totalWords based on current/previous character being a space
for
(
int
i
=
0
;
i
<
str_len
;
i
++
)
{
if
(
buff
[
i
]
!=
' '
&&
(
i
==
0
||
buff
[
i
-
1
]
==
' '
))
{
totalWords
++
;
}
}
return
totalWords
;
}
void
reverseString
(
char
*
buff
,
int
str_len
)
{
int
actual_length
=
0
;
for
(
int
i
=
0
;
i
<
str_len
;
i
++
)
{
if
(
buff
[
i
]
!=
'.'
)
{
actual_length
++
;
}
else
{
break
;
}
}
char
*
start
=
buff
;
char
*
end
=
buff
+
actual_length
-
1
;
while
(
start
<
end
)
{
char
temp
=
*
start
;
*
start
=
*
end
;
*
end
=
temp
;
start
++
;
end
--
;
}
}
void
printWords
(
char
*
buff
,
int
str_len
)
{
int
wordCounter
=
0
;
// Index of the word from the input
int
startIndex
=
-
1
;
// Tracks the start index of the word
printf
(
"Word Print
\n
----------
\n
"
);
for
(
int
i
=
0
;
i
<
str_len
;
i
++
)
{
// Ignore dots explicitly
if
(
buff
[
i
]
==
'.'
)
{
if
(
startIndex
!=
-
1
)
{
// Print the current word and reset startIndex
printf
(
"%.*s (%d)
\n
"
,
i
-
startIndex
,
&
buff
[
startIndex
],
i
-
startIndex
);
startIndex
=
-
1
;
}
continue
;
}
// Start of a new word. Keep track of characters.
if
(
buff
[
i
]
!=
' '
)
{
if
(
startIndex
==
-
1
)
{
wordCounter
++
;
startIndex
=
i
;
printf
(
"%d. "
,
wordCounter
);
}
}
// End of the current word. Reset the index for the next word
else
if
(
startIndex
!=
-
1
)
{
printf
(
"%.*s (%d)
\n
"
,
i
-
startIndex
,
&
buff
[
startIndex
],
i
-
startIndex
);
startIndex
=
-
1
;
}
}
// Prints output for the last word if it exists.
if
(
startIndex
!=
-
1
)
{
printf
(
"%.*s (%d)
\n
"
,
str_len
-
startIndex
,
&
buff
[
startIndex
],
str_len
-
startIndex
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
char
*
buff
;
// Placeholder 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?
// This code is safe because the first part of the if statement checks to make ensure if there are enough arguments.
// So if this first test fails, the second part won't be ran and the code exits.
if
((
argc
<
2
)
||
(
*
argv
[
1
]
!=
'-'
))
{
printf
(
"Error: Invalid option. Please try again.
\n
"
);
usage
(
argv
[
0
]);
exit
(
1
);
}
opt
=
(
char
)
*
(
argv
[
1
]
+
1
);
// handle the help flag and then exit normally
if
(
opt
==
'h'
)
{
usage
(
argv
[
0
]);
exit
(
0
);
}
//TODO: #2 Document the purpose of the if statement below
// This if statement makes sure that an input string is provided along with the command.
if
(
argc
<
3
)
{
printf
(
"Error: Missing input string.
\n
"
);
usage
(
argv
[
0
]);
exit
(
1
);
}
input_string
=
argv
[
2
];
//TODO: #3 Allocate space for the buffer using malloc and
// handle error if malloc fails by exiting with a
// return code of 99 and prints error message.
buff
=
(
char
*
)
malloc
(
BUFFER_SZ
*
sizeof
(
char
));
if
(
buff
==
NULL
)
{
printf
(
"Error: Memory allocation failed.
\n
"
);
exit
(
99
);
}
// Initialize buffer
for
(
int
i
=
0
;
i
<
BUFFER_SZ
;
i
++
)
{
buff
[
i
]
=
'.'
;
}
user_str_len
=
setup_buff
(
buff
,
input_string
,
BUFFER_SZ
);
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
;
case
'r'
:
reverseString
(
buff
,
user_str_len
);
// Print the reversed string without the dots
printf
(
"Reversed String: "
);
for
(
int
i
=
0
;
i
<
user_str_len
;
i
++
)
{
if
(
buff
[
i
]
!=
'.'
)
{
putchar
(
buff
[
i
]);
}
}
printf
(
"
\n
"
);
break
;
case
'w'
:
printWords
(
buff
,
user_str_len
);
break
;
case
'x'
:
if
(
argc
<
5
)
{
printf
(
"Error: Not enough arguments
\n
"
);
exit
(
1
);
}
printf
(
"Not implemented!
\n
"
);
break
;
//TODO: #5 Implement the other cases for 'r' and 'w' by extending
// the case statement options
default:
usage
(
argv
[
0
]);
exit
(
1
);
}
//TODO: #6 Don't 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?
//
// Passing the length makes it so that buffer overflows can be prevented since the helper functions are not aware of the size that is defined in main.
// It reduces risk and makes the code more future proof in case the size of the buffer changes.
// Finally, it makes the code more readable as the function's purpose can be observed easier and clearly.
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