一次C语言编程遇到的问题总结
今天用C语言做了一个简单的用户登录注册存取款等功能的系统,发现有很多功能并不会实现,大概是使用Java太多了导致许多C的知识都忘记了,现在把碰到的问题总结如下:
1、字符串复制问题
java等一些编程语言使用习惯了我们经常会用
String s1 = "abc";String s2 = s1
这种方式来给字符串赋值,但C语言一般使用的是char[]数组来存储字符串,所以在赋值的时候不可以使用单纯的赋值符"=",使用的是string.h头文件中包含的strcpy函数。如:
char a[];
char b[];
strcpy(a,b);
这样可以实现将b的值赋值给a。
2、字符串分隔问题
Java分隔字符串有专门的split函数来实现,C语言也有专门的函数实现,下面是一个实例:
char *p;
char StrLine[] = “a;b;c”;
p = strtok(StrLine,";");
while(p != NULL){
printf("%s\n",p);
p = strtok(NULL,";");
}
strtok函数:
原型:char *strtok(char s[], const char *delim);
介绍:分解字符串为一组字符串。s为要分解的字符,delim为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)。首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。
3、字符串转数字问题
例如现在有int a[3]={'1','2','3'}一个一维数组,如果要将其转换为123这个数字,我们可以这样:
1)计算a的长度,假设为n
2)分别将a[0]~a[n-1]转换为数字
3)这个数字就等于a[0]*10n-1+a[1]*10n-2+...+a[n-1]*100
这种方法确实可以实现,但是这种方法一是费时间二是费内存。
所以C语言有一个函数可以实现这种功能:atoi(a):
int atoi(const char *nptr) 函数会扫描参数 nptr字符串,会跳过前面的空白字符(例如空格,tab缩进)等。如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回 0 。特别注意,该函数要求被转换的字符串是按十进制数理解的。
附上简单实现用户登录注册存款取款修改密码的C语言代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h> //定义结构体User代表每一个用户
struct User{
char username[];//用户名
char password[];//密码
int deps;//存款数
}; struct User users[];//用户数组
struct User loginUser;//记录当前登录用户
int usersCount = ;//用户数量,默认为0 //读取文件信息
/*
由于读取文件过程中会自动读取所有数据下面的一个空行,
所以导致读取的userCount即用户数出现错误,比实际大一,
所以在执行完读取文件后,userCount需要减一
*/
void GetFileInfo(){
char *p;
char datas[][];
int i = ;
char fileName[] = "users.txt";
FILE *fp;
char StrLine[];
if((fp = fopen(fileName,"r")) == NULL)
{
printf("读取用户信息失败!");
return;
}
while(!feof(fp))
{
i = ;
fgets(StrLine,,fp);
p = strtok(StrLine," ");
while(p != NULL){
strcpy(datas[i++],p);
//printf("%s\n",p);
p = strtok(NULL," ");
}
strcpy(users[usersCount].username,datas[]);
strcpy(users[usersCount].password,datas[]);
users[usersCount].deps = atoi(datas[]);
usersCount ++;
}
usersCount -= ;
fclose(fp);
printf("读取用户信息成功~\n");
} //写入文件
void Update(){
int i = ;
FILE *fp;
fp = fopen("users.txt","w");
fclose(fp);
fp = fopen("users.txt","w");
for(i = ; i < usersCount; i++){
fprintf(fp,"%s %s %d\n",users[i].username,users[i].password,users[i].deps);
}
fclose(fp);
} //注册功能
struct User regist(){
char regist_username[];
char regist_password[];
struct User newUser;
printf("请输入用户名:");
scanf("%s",®ist_username);
printf("请输入六位密码:");
scanf("%s",®ist_password);
while(regist_password[]==NULL||regist_password[]!=NULL){
printf("密码必须是6位数,请重新输入密码:");
scanf("%s",®ist_password);
}
strcpy(newUser.username,regist_username);
strcpy(newUser.password,regist_password);
newUser.deps = ;//新注册用户余额为0
printf("注册成功!用户:%s\n",regist_username);
return newUser;
} //执行完操作后更新数组
void update(struct User user){
int i;
for(i = ; i < usersCount; i++){
if(strcmp(users[i].username,user.username) == ){
users[i] = user;
break;
}
}
} //登录后菜单选择
void menu(){
void Welcome();
int oper;
int deposit;
int withdraw;
char oldPass[];
char newPass[];
printf("***********\n");
printf("请选择:\n");
printf("1、存款\n");
printf("2、取款\n");
printf("3、查看余额\n");
printf("4、修改密码\n");
printf("5、返回\n");
printf("***********\n");
scanf("%d",&oper);
switch(oper){
case :
printf("请输入要存款的数额:");
scanf("%d",&deposit);
loginUser.deps += deposit;
printf("存款成功!余额为:%d\n",loginUser.deps);
update(loginUser);
Update();
menu();
break;
case :
printf("请输入要取款的数额:");
scanf("%d",&withdraw);
if(loginUser.deps >= withdraw){
loginUser.deps -= withdraw;
printf("取款成功!余额为:%d\n",loginUser.deps);
}else{
printf("余额不足!\n");
}
update(loginUser);
Update();
menu();
break;
case :
printf("用户:%s,您的余额为:%d\n",loginUser.username,loginUser.deps);
menu();
break;
case :
printf("请输入原密码:");
scanf("%s",&oldPass);
if(strcmp(oldPass,loginUser.password) == ){
printf("请输入新密码:");
scanf("%s",&newPass);
while(newPass[]==NULL||newPass[]!=NULL){
printf("密码必须是6位数,请重新输入密码:");
scanf("%s",&newPass);
}
strcpy(loginUser.password,newPass);
printf("更改密码成功!\n");
}else{
printf("原密码输入错误!\n");
}
update(loginUser);
Update();
menu();
break;
case :
Welcome();
}
} //登录功能
void login(){
void Welcome();
char login_username[];
char login_password[];
struct User checkUser;
int i;
printf("请输入用户名:");
scanf("%s",&login_username);
printf("请输入密码:");
scanf("%s",&login_password);
for(i = ; i < usersCount; i++){
if(strcmp(login_username,users[i].username) == ){
if(strcmp(login_password,users[i].password) == ){
loginUser = users[i];
printf("用户 %s欢迎登录!\n",login_username);
menu();
}else{
printf("密码输入错误!\n");
Welcome();
}
}
}
printf("没有这个用户!将返回\n");
Welcome();
} //欢迎界面
void Welcome(){
int select = ;
struct User user;
printf("*********************\n");
printf("欢迎来到ATM自助系统\n");
printf("*********************\n");
printf("请选择操作:\n1、用户登录\n2、用户注册\n3、退出系统\n");
scanf("%d",&select);
if(select == ){
login();
menu();
}else if (select == ){
user = regist();
users[usersCount] = user;
usersCount += ;
Update();
Welcome();
}else if (select == ){
printf("退出成功!");
exit();
}else{
printf("输入错误!将退出系统");
exit();
}
} //主函数
int main()
{
GetFileInfo();
Welcome();
return ;
}
一次C语言编程遇到的问题总结的更多相关文章
- C语言编程实现Linux命令——who
C语言编程实现Linux命令--who 实践分析过程 who命令是查询当前登录的每个用户,它的输出包括用户名.终端类型.登录日期及远程主机,在Linux系统中输入who命令输出如下: 我们先man一下 ...
- 个人c语言编程风格总结
总结一下我个人的编程风格及这样做的原因吧,其实是为了给实验室写一个统一的C语言编程规范才写的.首先声明,我下面提到的编程规范,是自己给自己定的,不是c语言里面规定的. 一件事情,做成和做好中间可能隔了 ...
- Linux下C语言编程实现spwd函数
Linux下C语言编程实现spwd函数 介绍 spwd函数 功能:显示当前目录路径 实现:通过编译执行该代码,可在终端中输出当前路径 代码实现 代码链接 代码托管链接:spwd.c 所需结构体.函数. ...
- 混合语言编程:启用CLR(公共语言运行时编译)让C#调用C++
前言 关于混合C#和C++的编程方式,本人之前写过一篇博客(参见混合语言编程:C#使用原生的Directx和OpenGL),在之前的博客中,介绍了在C#的Winform和WPF下使用原生的Direct ...
- Linux基础与Linux下C语言编程基础
Linux基础 1 Linux命令 如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命令行进行使用. 登录Linux后,我们就可以在#或$符后面去输入命令,有 ...
- LINUX下C语言编程基础
实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用 ...
- 第二章 C语言编程实践
上章回顾 宏定义特点和注意细节 条件编译特点和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法 第二章 第二章 C语言编程实践 C语言编程实践 预习检查 异或的运算符是什么 宏定义最主要的特点 ...
- 华为C语言编程规范
DKBA华为技术有限公司内部技术规范DKBA 2826-2011.5C语言编程规范2011年5月9日发布 2011年5月9日实施华为技术有限公司Huawei Technologies Co., Ltd ...
- 9 本免费的 Python 语言编程书籍(转载)
9 本免费的 Python 语言编程书籍 原文地址:http://linuxtoy.org/archives/9-free-python-books.html 2010-03-03 Toy Poste ...
- linux 操作系统下c语言编程入门
2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门--时间概念 5)Linux程序设计入门--信号处理 6)Linux程序设计入门--消息管理 ...
随机推荐
- ubutun18 install ibus-pinyin
ref: https://www.cnblogs.com/asmer-stone/p/9069866.html Step1 $ sudo apt-get install ibus-pinyin
- 隧道技术(Tunneling)
隧道技术及其应用 隧道技术(Tunneling)是一种通过使用互联网络的基础设施在网络之间传递数据的方式.使用隧道传递的数据(或负载)可以是不同协议的数据帧或包.隧道协议将其它协议的数据帧或包重新封装 ...
- 配置<welcome-file>为自定义路径
welcome-file是web.xml中的一个配置,其作用是配置启动项目时默认跳转的欢迎页面,一般我们会将其指定为一个静态页面. 那如果我们要将自定义的请求路径作为欢迎页面该怎么做呢? 1.配置we ...
- importlib 与__import__的区别
importlib 与__import__的区别 importlib import importlib name = "lib.test" # lib.test指的是lib路劲下的 ...
- vue.js使用更简单的方法制作带删除功能的tooolist
今天复习了下vue.js,先做了个基本版的todolist,做完后自己想加个删除本项的按钮.一开始做没啥头绪了,试了试无果,查了一把后发现网上的那些方法真的是麻烦,自己动手丰衣足食,自己最后换了思路试 ...
- redis学习笔记-02:为什么使用NoSQL数据库
一.第一代:单机版的MySQL 1.静态网页,动态交互类型的网站不多. 2.架构:APP---->DAL---->MySQL Instance 3.数据存储的瓶颈: (1)数据量总大小超过 ...
- bootstrap选项卡页面中如何关闭当前选项卡及页面
再具体说一下现在的需求: 如上界面:在新闻发布界面有一个按钮,在点击按钮的时候我需要直接把这个打开的选项卡关闭 实现思路: 1)关闭选项卡对应的页面 2)去除上方选项卡 3)激活前一 ...
- 闲谈“如何优化SSH框架的项目”
使用struts框架的好处之一就是所有action类继承一个基类,将访问控制在基类中处理.2.所有的action类都继承自baseaction,一个资源对应一个action类.1.实现一个继承自str ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 按钮:禁用状态
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 标准查询运算符---LINQ
Where 根据给定的谓词对序列进行过滤 Select 指定要包含一个对象或对象的一部分 SelectMany 一种查询类型,返回集合的集合.该方法将这些结果合并为一个单独的集合 Take 接受一个输 ...