Printing a C string in reverse without using pointers? - c

Is there a way to print a string of fixed size in reverse without using pointers?
#include<stdio.h>
main()
{
char buffer[10];
scanf("%s", buffer);
// need to print buffer in reverse without using pointers??
}

A lovely K&R function to reverse your string in-place before printing it, perhaps?
#include <stdio.h>
#include <string.h>
void strrev(char *s) {
int tmp, i, j;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
int main(int argc, const char *argv[]) {
char buffer[10];
scanf("%s", buffer);
strrev(buffer);
printf("%s\n", buffer);
return 0;
}

#include<stdio.h>
main()
{
char buffer[10];
int n = scanf("%s", buffer);
// print the number of chars written to buffer
if (n != EOF) {
int len = strlen(buffer);
if (len <= 10) {
int i;
for (i = len - 1; i >= 0; i--)
printf("%c", buffer[i]);
}
}
}

Since [] is just syntactic sugar for pointers, here's a version that works completely without pointers, arrays or anything else, just one single int. You didn't say that the string has to be stored somehow. :) (Note that I use fgetc instead of a buffer and scanf).
[jkramer/sgi5k:.../c]# cat rev.c
#include <stdio.h>
#include <stdlib.h>
void read_print();
int main(void) {
fputs("Enter your string, yo! ", stdout);
read_print();
fputs("\nDone!\n", stdout);
return EXIT_SUCCESS;
}
void read_print() {
int c = fgetc(stdin);
if(c != EOF && c != '\n') {
read_print();
fputc(c, stdout);
}
}
[jkramer/sgi5k:.../c]# gcc -o rev rev.c -Wall -W -Os
[jkramer/sgi5k:.../c]# ./rev
Enter your string, yo! foobar
raboof
Done!

Here's a recursive way of doing it; technically, this is using a pointer, but I wouldn't go into language-lawyer mode with such simple tasks.
#include <stdio.h>
/* If you want it printed forward, or backward, or think of another way.. */
typedef enum {
FRONT = 1,
BACK,
} direction;
/* Technically still using a pointer...don't nitpick. */
void echo_string(char buffer[], size_t buflen, direction from)
{
/* An index into the buffer to echo, which will preserve
* its value across subsequent recursive calls.
*/
static size_t index = 0;
/* According to the specified direction, print from the front
* or the back of the buffer. Advance the index (a misnomer, I guess).
*/
if(from == FRONT) {
printf("%c", buffer[index++]);
}
else {
printf("%c", buffer[buflen - ++index]);
}
/* Are there any more characters to echo? Yes? Awesome! */
if(index != buflen) {
echo_string(buffer, buflen, from);
}
}
int main(int argc, char **argv)
{
char buffer[10];
scanf("%s", buffer);
/* Better strlen() than sizeof() here,
* but BEWARE! scanf() is DANGEROUS!
*/
echo_string(buffer, strlen(buffer), BACK);
return(0);
}

reverse(char c[], int len)
{
if( ! (len / 2))
return;
char t = c[0];
c[0] = c[len--];
c[len] = t;
reverse(c, len-1);
}
The error(s) is left as an exercise to the student.

As caf pointed out, we're still using pointers..!
Here's an other way to solve the problem (of reversing a string).
This code snippet (and probably most others) don't respect stuff like utf8. I think signines post demonstrating the K&R way was quite close to mine (:D) so I adapted mine to fit that example (and corrected some things..)
#include <stdio.h>
#include <string.h>
void strrev(char *s) {
size_t len = strlen(s) + 1;
size_t i, j;
for(i = 0; i < len / 2; i++) {
j = len-1 - i-1;
char tmp = s[j];
s[j] = s[i];
s[i] = tmp;
}
}
int main(int argc, const char *argv[]) {
char buffer[10];
scanf("%s", buffer); // Look out for an overflow ;)
strrev(buffer);
puts(buffer);
return(0);
}

You can use strrev to reverse a string.
#include <stdio.h>
#include <string.h>
main()
{
char buffer[10];
scanf("%s", buffer);
strrev(buffer);
printf("%s", buffer);
}

void outstrreverse(const char s[])
{
size_t l=strlen(s);
while( l && s!=&s[--l] )
putchar(s[l]);
if(s[0])
putchar(s[0]);
}

Because of the relationship between C strings, arrays, and pointers the exercise is rather shotty IMHO - the most idiomatic description of a "String" in C is represented by the char*, which is not an array. Your (the OPs) title and post differ in their definitions between string and char[fixed length].
The OP should read and understand this FAQ entry, and between that and the posts here: easily figure out a solution—as well as defend it to the teacher/judge if need be.
I'll comment on this: never use scanf("%s", buffer) to populate a fixed length string. If you must use scanf() to do it, please use a field width specifier: e.g. scanf("%9s", buffer); if buffer is an [10], you want a specifier of 9 because of how scanf fills the buffer: otherwise you must beware the dragons! You could also scanf by character and evade the issue with a loops bounds, but that would likely be less efficient.

#include <stdio.h>
#include <conio.h>
void reverse(char a[], int s, int sc );
void reverse(char a[], int s, int sc ){
if ((sc-s)<(s-1))
{
a[sc-s]^=a[s-1];
a[s-1]^=a[sc-s];
a[sc-s]^=a[s-1];
reverse (a, s-1, sc) ;
}
}
void main (){
char a[]="ABCDEFG";
reverse(a, 7, 7);
printf("%d",a);
getch(); //i just use it to freeze the screen
}

Related

How do I write a recursive function to print a string in reverse in C?

I need any given string to be printed in reverse using recursion. I have tried changing the function prototype and definition by changing the return value type and parameter list of the function stringReverse. stdout of this does not print anything for the reverse string and I cannot figure out why.
#include <stdio.h>
#define SIZE 100
char stringReverse(void);
size_t i;
unsigned int pass;
int hold;
char a1[SIZE];
char a2[SIZE];
int main(void) {
for (i = 0; i < SIZE; ++i) {
a1[i] = 0;
}
printf("Enter a string: ");
scanf_s("%[^\n]99s", a1);
printf("%s%s\n\n", "string is:\n", a1);
stringReverse();
}
char stringReverse(void)
{
for (pass = 1; pass < SIZE; ++pass) {
if (a1[i] < a1[i + 1]) {
hold = a1[i];
a1[i] = a1[i + 1];
a1[i + 1] = hold;
}
}
printf("%s%s", "reverse is:\n", a2);
}
You do not have a recursive function that outputs a string in the reverse order. Also it is a bad idea when a function depends on a global variable.
The function can look the following way as it is shown in the demonstrative program below. Using the function you will be able to output a string in the reverse order in any stream for example in a file.
#include <stdio.h>
FILE * string_reverse_output( const char *s, FILE *fp )
{
if ( *s )
{
string_reverse_output( s + 1, fp );
fputc( *s, fp );
}
return fp;
}
int main(void)
{
fputc( '\n', string_reverse_output( "Hello World!", stdout ) );
return 0;
}
The program output is
!dlroW olleH
below are recursive functions to reverse a string the first is only prints and the second build the string inside revstr buffer and return it to caller.
void reverse(char *str)
{
if (*str)
{
reverse(str+1);
printf("%c", *str);
}
}
void recrev(char* str, char* revstr, int i)
{
if (*str)
{
recrev(str+1, revstr, i-1);
sprintf(revstr + i, "%c", *str);
}
}
int main()
{
char arr[]="hello";
char revstr[6];
recrev(arr, revstr, 4);
printf("%s",revstr);
return 0;
}
Recursion is a massive overkill for this job. But still, if need be, #VladfromMoscow has given an excellent answer using recursion. Might I take the liberty to instead suggest a better solution altogether?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
printf("Enter your string: ");
char str[100];
scanf("%[^\n]s",str);
str = strrev(str);
printf("%s",str);
return 0;
}
For more information on how strrev works, I suggest you take a look at strrev() function in C
#include <stdio.h>
void reverse();
int main()
{
printf("Enter String : ");
reverse();
return 0;
}
void reverse()
{
char c;
scanf("%c", &c);
if (c != '\n')
{
reverse();
printf("%c", c);
}
}

Attempting to code a c program to return a string length by dividing the code into two separate functions

I've been through several examples and videos and feel like there's a basic misconception on my part somewhere that I'm not seeing.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
char String;
char *sendString;
char getString[100];
int counter;
*sendString = String;
printf("\nPlease enter string:\n");
fgets(getString, 100, stdin);
int calcLength(counter);
printf("los1111: %d", counter);
return 0;
}
int calcLength()
{
char *sendString[100];
int counter;
for(counter = 0; *sendString[counter] != '\0'; counter++);
printf("los: %d", counter);
return counter;
}
there are a couple of test 'los' printf functions to see where the code is breaking but that unfortunately is bringing me up nothing. Any help is greatly appreciated.
I think your over complicating it slightly.
In this block of code:
char String;
char *sendString;
char getString[100];
int counter;
*sendString = String;
You don't need most of these char declarations, if you only want to calculate the length of the string from fgets.
This can simply be reduced to:
char getstring[100];
int myStrLen;
Where you only need to give a string buffer to fgets, and an integer declaration myStrLen, used to calculate the final string length.
Additionally, there are some problems with your calcLength() function. You need to pass a char [] parameter to this function, so it knows what string it needs to calculate the length of. It really should be as simple as this:
int
calcLength(char sendstring[]) {
int counter, len = 0;
for (counter = 0; sendstring[counter] != '\0'; counter++) {
len++;
}
return len;
}
With all of these recommendations, your code should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 100
int calcLength(char sendstring[]);
int
main(void) {
char getstring[BUFFSIZE];
int myStrLen;
printf("\nPlease enter string:\n");
if (fgets(getstring, BUFFSIZE, stdin) != NULL) {
getstring[strlen(getstring)-1] = '\0'; // To remove '\n' character from fgets()
}
myStrLen = calcLength(getstring);
printf("String length = %d\n", myStrLen);
return 0;
}
int
calcLength(char sendstring[]) {
int counter, len = 0;
// Every valid character found, increment a counter
for (counter = 0; sendstring[counter] != '\0'; counter++) {
len++;
}
return len;
}
Note: This code can be improved, but it should help point you in the right direction. I've added some comments in the code for clarification.

Remove specified char from strings in C

I am making a program that will search in an array of strings, and for each string, it will search for a specified char. If it finds that char, remove it. In this example I want to remove the character 'r'.
Here is the code:
void convertStrings(char **line) {
for (int str = 0; str < MAX_LINE_LENGTH; ++str) {
for (int ch = 0; ch < MAX_STR_LENGTH; ++ch) {
if (line[str][ch] == 'r') {
removeChar(line[str], 'r');
}
}
}
}
void removeChar(char *str, char c) {
int i = 0;
int j = 0;
while (str[i]) {
if (str[i] != c) {
str[j++] = str[i];
}
i++;
}
str[j]=0;
}
I am not sure if the algorithm for the removal of chars is correct, however the main mistake is elsewhere. More specifically, I get a segmentation fault in the line:
if (line[str][ch] == 'r') {
Why am I getting a seg fault? Also, is the algorithm for removeChar correct?
Here is my main function:
int main() {
char line[3][10] = {"pep", "rol", "rak"};
printf("%s\n", line[1]);
convertStrings(line);
printf("%s\n", line[1]);
return 0;
}
Thanks in advance.
This code works on my compiler :
#include<stdio.h>
#include<conio.h>
#define MAX_LINE_LENGTH 1024
#define MAX_STR_LENGTH 4
void removeChar(char *str, char c) {
int i = 0;
int j = 0;
while (str[i]) {
if (str[i] != c) {
str[j++] = str[i];
}
i++;
}
str[j]=0;
}
void convertStrings(char line[][MAX_STR_LENGTH]) { //change 1
for (int str = 0; str < MAX_LINE_LENGTH; ++str) {
for (int ch = 0; ch < MAX_STR_LENGTH; ++ch) {
if (line[str][ch] == 'r') {
removeChar(line[str], 'r');
}
}
}
}
int main() {
char line[3][MAX_STR_LENGTH] = {"pep", "rol", "rak"}; //change 2
printf("%s\n", line[1]);
convertStrings(line);
printf("%s\n", line[1]);
getch();
return 0;
}
It's because line[str][ch] doesn't exist for all the value you give to str and/or ch.
You should check the value of MAX_LINE_LENGTH and MAX_STR_LENGTH and be sure that they are right.
The seg fault may be because you are using the constants "MAX_LINE_LENGTH" and "MAX_STR_LENGTH" however there may have the line length or string length. I would use the length of the array for the variable str in the first for loop instead of "MAX_LINE_LENGTH" and the length of array[str] instead of "MAX_STR_LENGTH". Unless each array you are searching has "MAX_LINE_LENGTH" and each string has "MAX_LINE_LENGTH" you will get a set fault. Hope this helps!
EDIT: you can find the length of the array by dividing the size of the array and the size of the type of the element.
sizeof(array)/sizeof(array[0])
finding the size of the char pointer is basically the same process.
You are getting a segfault either because array line contains fewer than MAX_LINE_LENGTH string pointers, or because at least one of the pointed-to strings contains fewer than MAX_STR_LENGTH characters; more likely the latter.
Instead of assuming a fixed number of strings of fixed length, you would be better off passing the actual number of strings as an argument. Alternatively, you could add NULL as sentinel value at the end of the list.
Moreover, there is no reason whatever to assume that each string is a fixed length. Look for the terminating character ('\0') to recognize when you've reached the end. For example:
void convertStrings(char **line) {
for (char **l = line; *l != NULL; l += 1) {
for (int ch = 0; (*l)[ch]; ch += 1) {
if ((*l)[ch] == 'r') {
removeChar(*l, 'r');
}
}
}
}
Your removeChar() function looks ok.
Do note, however, that there are library functions that could help with this (e.g. strchr()), and that there are various efficiency improvements possible (such as passing to removeChar() only the string tail, starting at the first appearance of the character to remove).
You have the array
char line[3][10] = {"pep", "rol", "rak"};
When you pass it to a function, it gets converted into a pointer of type char(*)[10]. So change
void convertStrings(char **line) {
to
void convertStrings(char (*line)[10]) {
or
void convertStrings(char line[][10]) {
An array of arrays (2D array) cannot be converted to a pointer to a pointer(in this case, char**)
Another problem is that you mention that MAX_LINE_LENGTH is 1024 and MAX_STR_LENGTH is 4. This is wrong as the loop would iterate and you access invalid memory locations. You should make MAX_LINE_LENGTH as 3 and MAX_STR_LENGTH as 4 as there are 3 strings, each with 4 characters.
You can also pass these variables as parameters to the function convertStrings. Change add two more parameters in the declartion of convertStrings:
void convertStrings(char (*line)[10], int MAX_LINE_LENGTH, int MAX_STR_LENGTH) {
or
void convertStrings(char line[][10], int MAX_LINE_LENGTH, int MAX_STR_LENGTH) {
and call the function from main using
convertStrings(line, sizeof(line)/sizeof(*line), sizeof(*line)/sizeof(**line)); // `/sizeof(**line)` is 1 and is not needed
A better way would be to use
void convertStrings(int MAX_LINE_LENGTH, int MAX_STR_LENGTH, char line[][MAX_STR_LENGTH]) {
or
void convertStrings(int MAX_LINE_LENGTH, int MAX_STR_LENGTH, char (*line)[MAX_STR_LENGTH]) {
and call the function using
convertStrings(sizeof(line)/sizeof(*line), sizeof(*line)/sizeof(**line), line); // `/sizeof(**line)` is 1 and is not needed
so that you can avoid using the magic number 10 in your function.
You would've certainly got some warnings from your compiler. Pay attention to them. If you did not get warnings, crank up the warnings in your compiler and include warning flags ( like -Wall in GCC ).
BTW, You can look into the strchr function from string.h to find if a character exists in a string.
Why do you check if you encounter the 'r' character twice? (in both function)
checking once would be enough.
A function to detect the char, and a function to delete it?
I would have done it this way :
#include <string.h>
#include <stdio.h>
void convertStrings(char *line);
void removeChar(char *str);
int main(int argc, char *argv[]) {
if (argc == 2)
{
printf("%s\n", argv[1]);
convertStrings(argv[1]);
printf("%s\n", argv[1]);
}
return (0);
}
void convertStrings(char *line)
{
for (int i = 0; line[i] != '\0'; i++)
{
if (line[i] == 'r') removeChar(&(line[i]));
}
}
void removeChar(char *str)
{
int i;
i = 0;
while (str[i] != '\0')
{
str[i] = str[i + 1];
i++;
}
}
But here is another one solution with only one function :
void convertStringsbis(char *line)
{
int delta;
int i;
i = 0;
delta = 0;
while (line[i++ + delta] != '\0')
{
if (line[i + delta] == 'r')
delta++;
line[i] = line[i + delta];
}
}

Getting a segmentation fault in my code

My code is giving me a segmentation fault. I'm 99% sure the fault is stemming from my lousy code construction.
#include <stdio.h>
#include <assert.h>
#include <string.h>
int decToBit(unsigned int I, char *str){
str = "";
int currentVal = I;
do{
if(I%2 == 0)
strcat(str,"0");
else
strcat(str,"1");
} while(currentVal > 0);
return(0);
}
You need to make sure that there is enough space in str to add the extra characters:
char myStr[200];
myStr[0] = '\0'; // make sure you start with a "zero length" string.
strcpy(myStr, str);
and then use myStr where you were using str.
As it is, the statement
str="";
points str to a const char* - that is a string you can read but not write.
Incidentally the call signature for main is
int main(int argc, char *argv[])
in other words, you need a pointer to a pointer to char. If I am not mistaken, you would like to do the following (a bit of mind reading here):
Every odd argument gets a 1 added; every even argument gets a 0 added.
If my mind reading trick worked, then you might want to try this:
#include <stdio.h>
#include <string.h>
int main(int argc, char * argv[]) {
char temp[200];
temp[0] = '\0';
int ii;
for(ii = 0; ii < argc; ii++) {
strncpy(temp, argv[ii], 200); // safe copy
if(ii%2==0) {
strcat(temp, "0");
}
else {
strcat(temp, "1");
}
printf("%s\n", temp);
}
}
edit just realized you edited the question and now your purpose is much clearer.
Modified your function a bit:
int decToBit(unsigned int I, char *str){
str[0] = '\0';
char *digit;
do
{
digit = "1";
if ( I%2 == 0) digit = "0";
strcat(str, digit);
I>>=1;
} while (I != 0);
return(0);
}
It seems to work...
In do-while loop you should increment the value of currentVal. Otherwise it will be an infinity loop and you will end up with Segmentation fault.
Initialize str[0] properly.
Divide I by 2 each loop.
But then the string will be in a little endian order. Doubt that was intended?
int decToBit(unsigned int I, char *str) {
str[0] = '\0';
do {
if (I%2 == 0)
strcat(str,"0");
else
strcat(str,"1");
I /= 2;
} while(I > 0);
return(0);
}
// call example
char buf[sizeof(unsigned)*CHAR_BIT + 1];
decToBit(1234567u, buf);
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
char *decToBit(unsigned int I, char *str){
int bit_size = CHAR_BIT * sizeof(I);
str += bit_size;
*str = 0;
do{
*--str = "01"[I & 1];
}while(I>>=1);
return str;
}
int main(){
char bits[33];
printf("%s\n", decToBit(0, bits));
printf("%s\n", decToBit(-1, bits));
printf("%s\n", decToBit(5, bits));
return 0;
}

Returning a string to a variable length character array

I have a program that reverses a string from an input of a variable length character array. The function returns a variable length character array and is printed. When I print the output, I do get the reversed string, but there are garbage characters appended to it in my console print.
Is this a "legal" operation in terms of returning to buffers? Can someone please critique my code and suggest a better alternative if it is not the right approach?
Thanks.
#include <stdio.h>
#include <stdlib.h>
char *reverse_string(char *input_string);
char *reverse_string(char *input_string)
{
int i=0;
int j=0;
char *return_string;
char filled_buffer[16];
while (input_string[i]!='\0')
i++;
while (i!=0)
{
filled_buffer[j]=input_string[i-1];
i--;
j++;
}
return_string=filled_buffer;
printf("%s", return_string);
return return_string;
}
int main (void)
{
char *returned_string;
returned_string=reverse_string("tasdflkj");
printf("%s", returned_string);
return 1;
}
This is my output from Xcode - jklfdsat\347\322̲\227\377\231\235
No, it isn't safe to return a pointer to a local string in a function. C won't stop you doing it (though sometimes the compiler will warn you if you ask it to; in this case, the local variable return_string prevents it giving the warning unless you change the code to return filled_buffer;). But it is not safe. Basically, the space gets reused by other functions, and so they merrily trample on what was once a neatly formatted string.
Can you explain this comment in more detail — "No, it isn't safe..."
The local variables (as opposed to string constants) go out of scope when the function returns. Returning a pointer to an out-of-scope variable is undefined behaviour, which is something to be avoided at all costs. When you invoke undefined behaviour, anything can happen — including the program appearing to work — and there are no grounds for complaint, even if the program reformats your hard drive. Further, it is not guaranteed that the same thing will happen on different machines, or even with different versions of the same compiler on your current machine.
Either pass the output buffer to the function, or have the function use malloc() to allocate memory which can be returned to and freed by the calling function.
Pass output buffer to function
#include <stdio.h>
#include <string.h>
int reverse_string(char *input_string, char *buffer, size_t bufsiz);
int reverse_string(char *input_string, char *buffer, size_t bufsiz)
{
size_t j = 0;
size_t i = strlen(input_string);
if (i >= bufsiz)
return -1;
buffer[i] = '\0';
while (i != 0)
{
buffer[j] = input_string[i-1];
i--;
j++;
}
printf("%s\n", buffer);
return 0;
}
int main (void)
{
char buffer[16];
if (reverse_string("tasdflkj", buffer, sizeof(buffer)) == 0)
printf("%s\n", buffer);
return 0;
}
Memory allocation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverse_string(char *input_string);
char *reverse_string(char *input_string)
{
size_t j = 0;
size_t i = strlen(input_string) + 1;
char *string = malloc(i);
if (string != 0)
{
string[--i] = '\0';
while (i != 0)
{
string[j] = input_string[i-1];
i--;
j++;
}
printf("%s\n", string);
}
return string;
}
int main (void)
{
char *buffer = reverse_string("tasdflkj");
if (buffer != 0)
{
printf("%s\n", buffer);
free(buffer);
}
return 0;
}
Note that the sample code includes a newline at the end of each format string; it makes it easier to tell where the ends of the strings are.
This is an alternative main() which shows that the allocated memory returned is OK even after multiple calls to the reverse_string() function (which was modified to take a const char * instead of a plain char * argument, but was otherwise unchanged).
int main (void)
{
const char *strings[4] =
{
"tasdflkj",
"amanaplanacanalpanama",
"tajikistan",
"ablewasiereisawelba",
};
char *reverse[4];
for (int i = 0; i < 4; i++)
{
reverse[i] = reverse_string(strings[i]);
if (reverse[i] != 0)
printf("[%s] reversed [%s]\n", strings[i], reverse[i]);
}
for (int i = 0; i < 4; i++)
{
printf("Still valid: %s\n", reverse[i]);
free(reverse[i]);
}
return 0;
}
Also (as pwny pointed out in his answer before I added this note to mine), you need to make sure your string is null terminated. It still isn't safe to return a pointer to the local string, even though you might not immediately spot the problem with your sample code. This accounts for the garbage at the end of your output.
First, returning a pointer to a local like that isn't safe. The idiom is to receive a pointer to a large enough buffer as a parameter to the function and fill it with the result.
The garbage is probably because you're not null-terminating your result string. Make sure you append '\0' at the end.
EDIT: This is one way you could write your function using idiomatic C.
//buffer must be >= string_length + 1
void reverse_string(char *input_string, char* buffer, size_t string_length)
{
int i = string_length;
int j = 0;
while (i != 0)
{
buffer[j] = input_string[i-1];
i--;
j++;
}
buffer[j] = '\0'; //null-terminate the string
printf("%s", buffer);
}
Then, you call it somewhat like:
#define MAX_LENGTH 16
int main()
{
char* foo = "foo";
size_t length = strlen(foo);
char buffer[MAX_LENGTH];
if(length < MAX_LENGTH)
{
reverse_string(foo, buffer, length);
printf("%s", buffer);
}
else
{
printf("Error, string to reverse is too long");
}
}

Resources