- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
关于这个程序可能有人问过不同的问题,但是在这个 C 代码中我有三个函数:一个打印记录,一个添加记录,一个删除记录。
我不明白的是为什么(添加)和(删除)不在主函数中进行更改,所以当我使用打印所有记录
它打印更改的功能,但不显示更改,有什么问题吗?
详细信息在评论中,请随时运行代码以可视化问题。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*The program is to store student record (firstname,lastname and score), it should not be more
than 15 records and the names should not be more than 20 chars, array pointersnare being used
instead of arrays, the (add_record) and (delete_record) functions must
do thsi change in the main function, so when you print all records, the changes are shown*/
void print_records(char **firstname,char **lastname,float *score,int *the_size)
{
int i;
printf("Printing All record(s)...\n");
for (i=0;i<*the_size;i++) /*loop to print records of all arrays in correct format*/
{
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[i],lastname[i],score[i]);
}
}
void add_new_record (char **firstname,char **lastname,float *score,int the_size)
{
printf("Add new record in the format :\nFirstname Lastname Score\n");
/*the strategy here is to check if all 15 elemts are used, if they are, use realloc
to add one more, if not add the record after the last record*/
if (the_size == 15)
{
firstname=realloc(firstname,16*sizeof(char*));
firstname[15]=malloc((20+1)*sizeof(char));
lastname=realloc(lastname,16*sizeof(char*));
lastname[15]=malloc((20+1)*sizeof(char));
score=realloc(score,16*sizeof(float));
scanf("%s %s %f",firstname[15],lastname[15],&score[15]);
printf("New Record Added Successfully !\n");
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[15],lastname[15],score[15]);
}
else if (the_size<15)
{
scanf("%s %s %f",firstname[the_size],lastname[the_size],&score[the_size]);
printf("New Record Added Successfully !\n");
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[the_size],lastname[the_size],score[the_size]);
}
}
void delete_record (char **firstname,char **lastname,float *score,int the_size)
{
char *str=malloc(20*sizeof(char)); /*String entered by user must be 20 or less chars*/
int i,ctr=0;
char *temp_first=malloc(20*sizeof(char));/*temp array to swap firstname must be 20 or less chars*/
char *temp_last=malloc(20*sizeof(char)); /*temp array to swap lastname must be 20 or less chars*/
float temp_score;/*ctr is the counter used to check if there are no matchs in the end*/
printf("Enter the lastname of record(s) to delete : ");
scanf("%s",str);
/* the strategy here is to move the element to be deleted to the last index and use
relloc to shrink the size by 1 (-1) */
for (i=0;i< the_size;i++)
{
if (strcmp(str,lastname[i])==0)
{
printf("Deleting Record for %s %s...\n",firstname[i],lastname[i]);
temp_score=score[i];
score[i]=score[the_size-1];
score[the_size-1]=temp_score;
strcpy(temp_first, firstname[i]); /*using strcpy function to swap strings*/
strcpy(firstname[i], firstname[the_size-1]);
strcpy(firstname[the_size-1], temp_first);
strcpy(temp_last, lastname[i]);
strcpy(lastname[i], lastname[the_size-1]);
strcpy(lastname[the_size-1], temp_last);
score=realloc(score,(the_size-1)*sizeof(float));
firstname=realloc(firstname,(the_size-1)*sizeof(char*));
lastname=realloc(lastname,(the_size-1)*sizeof(char*));
ctr++;
the_size--;
}
}
if (!ctr) /*if ctr=0 (no increment), then print,there is no match*/
{
printf ("Sorry, no available record for %s",str);
}
free(temp_first);
free(temp_last);
free(str);
}
void main()
{
char **firstname;
char **lastname;
float *score;
int number_of_records,i,j=-1,ctr=1,row=15,col=20;
/*ctr is to keep track of the student's number (makes it easier to
the user), it starts with (1)*/
firstname=malloc(row*sizeof(char*));
for(i=0;i<row;i++)
{
firstname[i]=malloc((col+1)*sizeof(char));
}
lastname=malloc(row*sizeof(char*));
for(i=0;i<row;i++)
{
lastname[i]=malloc((col+1)*sizeof(char));
}
printf("\nPlease indicate number of records you want to enter (min 2, max 15): ");
scanf("%d",&number_of_records);
score=malloc(row*sizeof(float));
printf("\nPlease input records of students\n(enter a new line after"
"each record), with following format:\nfirst name last name score ");
for (i=0;i<number_of_records;i++)
{
printf("\nEnter record for student %d : ",ctr);
scanf("%s %s %f",firstname[i],lastname[i],&score[i]);
ctr++; /*ctr is to keep track of student number
(makes it easy to the user) */
}
while (j!=0) /*Main menu will keep looping after using a function as long as j is not 0
When the user enters 0 (zero) the loop will stop and therefore the program will terminate*/
{
printf("\nSelect desired function by pressing the corresponding key number\n");
printf("\n********** Main Menu **********\n");
printf("\n>>> Print records (press 1)\n");
printf("\n>>> Add a new Record (press 2 )\n");
printf("\n>>> delete record (press 3)\n");
printf("\n>>> Exit the program (press 0)\n");
scanf("%d",&j); /*getting j from the user (j is used for selection and for the while loop)*/
if (j==1)
{
print_records(firstname,lastname,score,&number_of_records);
}
else if (j==2)
{
add_new_record(firstname,lastname,score,number_of_records);
}
else if (j==3)
{
delete_record(firstname,lastname,score,number_of_records);
}
else if (j==0)
{
printf("Exitting program ...\n");
}
}
}
最佳答案
正如其他答案所观察到的,在 C 中,所有参数都是按值传递的。这意味着该函数获取调用者值的副本,因此对该值的更改对调用者不可见。换句话说,给定
void f(any_type arg) {
arg = any_value;
}
无论any_type
是什么类型或any_value
是什么值,调用者永远不会检测到任何变化。但是,请仔细注意那个和这个之间的区别:
void f(any_type *arg) {
*arg = any_value;
}
在那种情况下,被修改的不是函数参数(指针),而是指向的东西。参数是调用者值的副本,因此两者指向同一事物。调用者无法检测到参数的变化,但在调用之后,它可以检测到它所指向的事物的变化。
您的代码出现了一些此类问题,其中一些问题导致了您的主要问题。最重要的是,这些与您对列表中元素数量的记录有关(main()
中的变量 number_of_records
)。您的添加和删除功能或多或少可以正常工作,除了它们无法将修改后的列表大小传回 main。
当已经有 15 条记录时,add_new_record()
中还有其他问题;如果可以的话,我会拒绝这种情况。如果你必须支持它,那么你有很多事情需要清理。其中一些与按值传递问题有关,另一些与您的代码在列表最初包含 16 或更多记录时应该执行的操作有关。
更新:由于您在解决这个问题时遇到了很多麻烦,这里是 delete_record()
的修订版本。它实现的不仅仅是删除记录时获得所需输出所需的最小更改,因为实际上还有很多其他问题,只要我遇到麻烦,我也可以提出来。查看新评论和修改后的评论。
/*
* Can realloc() *firstname, *lastname, and *score and return the updated
* values to the caller. Most importantly, can update *the_size and have
* the caller see the result.
*/
void delete_record (char ***firstname, char ***lastname, float **score, int *the_size)
{
int i;
int initial_size = *the_size;
char str[21]; /* no need to malloc a fixed-length local array */
printf("Enter the lastname of record(s) to delete : ");
fflush(stdout); /* The prompt might not appear if you don't flush */
/*
* Note the field width in the format below. Without it, a user can
* easily cause a buffer overflow.
*/
scanf("%20s", str);
/*
* The strategy for each element to delete (there may be more than one)
* is to free the element's name components (else their allocated memory
* leaks), copy the last (at that time) element's components into
* place (for the name components, just the pointers), and later
* realloc to shrink the overall size to exactly fit the remaining
* elements (once we know how many that is).
*/
for (i = 0; i < *the_size; )
{
if (strcmp(str, (*lastname)[i]) == 0)
{
printf("Deleting Record for %s %s...\n", (*firstname)[i], (*lastname)[i]);
free((*firstname)[i]);
free((*lastname)[i]);
(*firstname)[i] = (*firstname)[*the_size - 1];
(*lastname)[i] = (*lastname)[*the_size - 1];
(*score)[i] = (*score)[*the_size - 1];
*the_size -= 1; /* not the same as *the_size-- */
/* don't increment i, else we miss testing the new i'th element */
} else {
i += 1;
}
}
if (*the_size != initial_size)
{
void *temp;
/*
* Always check the return value of realloc(), even when you're
* shrinking the allocation. Usually, though, you'd want at least
* some kind of diagnostic in the event of failure.
*/
temp = realloc(*firstname, sizeof(char *) * (*the_size));
if (temp)
{
*firstname = temp;
}
temp = realloc(*lastname, sizeof(char *) * (*the_size));
if (temp)
{
*lastname = temp;
}
temp = realloc(*score, sizeof(float) * (*the_size));
if (temp)
{
*score = temp;
}
}
else /* there is no match */
{
printf ("Sorry, no available record for %s",str);
}
}
您的 main()
会这样调用:
delete_record(&firstname, &lastname, &score, &number_of_records);
需要对 add_record()
进行类似的更改,尽管您确实遇到了我已经指出的单独问题,即条目数增加到 16 以上。
此外,您通过使用单独的名字、姓氏和分数数组为自己做额外的工作。定义一个包含所有这三个结构的 struct
并只使用一个其元素是该 struct
实例的动态数组会容易得多。
关于c - 如何正确地将数组指针传递给 C 中的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29834822/
Github:https://github.com/jjvang/PassIntentDemo 我一直在关注有关按 Intent 传递对象的教程:https://www.javacodegeeks.c
我有一个 View ,其中包含自动生成的 text 类型的 input 框。当我单击“通过电子邮件发送结果”按钮时,代码会将您带到 CalculatedResults Controller 中的 Em
我有一个基本的docker镜像,我将以此为基础构建自己的镜像。我没有基础镜像的Dockerfile。 基本上,基本镜像使用两个--env arg,一个接受其许可证,一个选择在容器中激活哪个框架。我可以
假设我想计算 2^n 的总和,n 范围从 0 到 100。我可以编写以下内容: seq { 0 .. 100 } |> Seq.sumBy ((**) 2I) 但是,这与 (*) 或其他运算符/函数不
我有这个网址: http://www.example.com/get_url.php?ID=100&Link=http://www.test.com/page.php?l=1&m=7 当我打印 $_G
我想将 window.URL.createObjectURL(file) 创建的地址传递给 dancer.js 但我得到 GET blob:http%3A//localhost/b847c5cd-aa
我想知道如何将 typedef 传递给函数。例如: typedef int box[3][3]; box empty, *board[3][3]; 我如何将 board 传递给函数?我
我正在将一些代码从我的 Controller 移动到核心数据应用程序中的模型。 我编写了一个方法,该方法为我定期发出的特定获取请求返回 NSManagedObjectID。 + (NSManagedO
为什么我不能将类型化数组传递到采用 any[] 的函数/构造函数中? typedArray = new MyType[ ... ]; items = new ko.observableArray(ty
我是一名新的 Web 开发人员,正在学习 html5 和 javascript。 我有一个带有“选项卡”的网页,可以使网页的某些部分消失并重新出现。 链接如下: HOME 和 JavaScript 函
我试图将对函数的引用作为参数传递 很难解释 我会写一些伪代码示例 (calling function) function(hello()); function(pass) { if this =
我在尝试调用我正在创建的 C# 项目中的函数时遇到以下错误: System.Runtime.InteropServices.COMException: Operation is not allowed
使用 ksh。尝试重用当前脚本而不修改它,基本上可以归结为如下内容: `expr 5 $1 $2` 如何将乘法命令 (*) 作为参数 $1 传递? 我首先尝试使用“*”,甚至是\*,但没有用。我尝试
我一直在研究“Play for Java”这本书,这本书非常棒。我对 Java 还是很陌生,但我一直在关注这些示例,我有点卡在第 3 章上了。可以在此处找到代码:Play for Java on Gi
我知道 Javascript 中的对象是通过引用复制/传递的。但是函数呢? 当我跳到一些令人困惑的地方时,我正在尝试这段代码。这是代码片段: x = function() { console.log(
我希望能够像这样传递参数: fn(a>=b) or fn(a!=b) 我在 DjangoORM 和 SQLAlchemy 中看到了这种行为,但我不知道如何实现它。 最佳答案 ORM 使用 specia
在我的 Angular 项目中,我最近将 rxjs 升级到版本 6。现在,来自 npm 的模块(在 node_modules 文件夹内)由于一些破坏性更改而失败(旧的进口不再有效)。我为我的代码调整了
这个问题在这里已经有了答案: The issue of * in Command line argument (6 个答案) 关闭 3 年前。 我正在编写一个关于反向波兰表示法的 C 程序,它通过命
$(document).ready(function() { function GetDeals() { alert($(this).attr("id")); } $('.filter
下面是一个例子: 复制代码 代码如下: use strict; #这里是两个数组 my @i =('1','2','3'); my @j =('a','b','c'); &n
我是一名优秀的程序员,十分优秀!